diff --git a/doc/hotspot-unit-tests.html b/doc/hotspot-unit-tests.html index 556cfecc42d..fcd4a93f8e4 100644 --- a/doc/hotspot-unit-tests.html +++ b/doc/hotspot-unit-tests.html @@ -245,7 +245,7 @@

Error messages

All GoogleTest asserts print compared expressions and their values, so there is no need to have them in error messages. Asserts print only compared values, they do not print any of interim variables, e.g. -ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18) +ASSERT_TRUE((val1 == val2 && isFail(foo(8))) || i == 18) prints only one value. If you use some complex predicates, please consider EXPECT_PRED* or EXPECT_FORMAT_PRED assertions family, they check that a predicate returns true/success and diff --git a/doc/hotspot-unit-tests.md b/doc/hotspot-unit-tests.md index 62ace4ef6ee..e1222baa2e3 100644 --- a/doc/hotspot-unit-tests.md +++ b/doc/hotspot-unit-tests.md @@ -172,7 +172,7 @@ Provide informative, but not too verbose error messages. All GoogleTest asserts print compared expressions and their values, so there is no need to have them in error messages. Asserts print only compared values, they do not print any of interim variables, e.g. -`ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18)` prints only +`ASSERT_TRUE((val1 == val2 && isFail(foo(8))) || i == 18)` prints only one value. If you use some complex predicates, please consider `EXPECT_PRED*` or `EXPECT_FORMAT_PRED` assertions family, they check that a predicate returns true/success and print out all parameters values. diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 1052e422f7b..272cb1af0a6 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -96,8 +96,6 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED \ --add-exports java.base/jdk.internal.util=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \ --add-exports java.base/jdk.internal.vm=ALL-UNNAMED \ --add-exports java.base/sun.invoke.util=ALL-UNNAMED \ --add-exports java.base/sun.security.util=ALL-UNNAMED \ diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 836caa86cb0..017e86a9dc3 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -503,7 +503,7 @@ void InterpreterMacroAssembler::remove_activation( // get method access flags ldr(r1, Address(rfp, frame::interpreter_frame_method_offset * wordSize)); - ldr(r2, Address(r1, Method::access_flags_offset())); + ldrh(r2, Address(r1, Method::access_flags_offset())); tbz(r2, exact_log2(JVM_ACC_SYNCHRONIZED), unlocked); // Don't unlock anything if the _do_not_unlock_if_synchronized flag diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index fa48092fd50..6010ddd25fe 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -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. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -760,7 +760,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label L_skip_barrier; { // Bypass the barrier for non-static methods - __ ldrw(rscratch1, Address(rmethod, Method::access_flags_offset())); + __ ldrh(rscratch1, Address(rmethod, Method::access_flags_offset())); __ andsw(zr, rscratch1, JVM_ACC_STATIC); __ br(Assembler::EQ, L_skip_barrier); // non-static } diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index f70450b7222..0a3240fa56e 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -809,7 +809,7 @@ void TemplateInterpreterGenerator::lock_method() { #ifdef ASSERT { Label L; - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); __ tst(r0, JVM_ACC_SYNCHRONIZED); __ br(Assembler::NE, L); __ stop("method doesn't need synchronization"); @@ -820,7 +820,7 @@ void TemplateInterpreterGenerator::lock_method() { // get synchronization object { Label done; - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); __ tst(r0, JVM_ACC_STATIC); // get receiver (assume this is frequent case) __ ldr(r0, Address(rlocals, Interpreter::local_offset_in_bytes(0))); @@ -1225,7 +1225,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // make sure method is native & not abstract #ifdef ASSERT - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); { Label L; __ tst(r0, JVM_ACC_NATIVE); @@ -1277,7 +1277,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { #ifdef ASSERT { Label L; - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); __ tst(r0, JVM_ACC_SYNCHRONIZED); __ br(Assembler::EQ, L); __ stop("method needs synchronization"); @@ -1354,7 +1354,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // pass mirror handle if static call { Label L; - __ ldrw(t, Address(rmethod, Method::access_flags_offset())); + __ ldrh(t, Address(rmethod, Method::access_flags_offset())); __ tbz(t, exact_log2(JVM_ACC_STATIC), L); // get mirror __ load_mirror(t, rmethod, r10, rscratch2); @@ -1564,7 +1564,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // do unlocking if necessary { Label L; - __ ldrw(t, Address(rmethod, Method::access_flags_offset())); + __ ldrh(t, Address(rmethod, Method::access_flags_offset())); __ tbz(t, exact_log2(JVM_ACC_SYNCHRONIZED), L); // the code below should be shared with interpreter macro // assembler implementation @@ -1695,7 +1695,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // make sure method is not native & not abstract #ifdef ASSERT - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); { Label L; __ tst(r0, JVM_ACC_NATIVE); @@ -1751,7 +1751,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef ASSERT { Label L; - __ ldrw(r0, access_flags); + __ ldrh(r0, access_flags); __ tst(r0, JVM_ACC_SYNCHRONIZED); __ br(Assembler::EQ, L); __ stop("method needs synchronization"); diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp index 3a81fdddb3c..b70a4b495b2 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.cpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -736,7 +736,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, Register ret_a ldrb(Rflag, do_not_unlock_if_synchronized); // get method access flags - ldr_u32(Raccess_flags, Address(Rmethod, Method::access_flags_offset())); + ldrh(Raccess_flags, Address(Rmethod, Method::access_flags_offset())); strb(zero_register(Rtemp), do_not_unlock_if_synchronized); // reset the flag diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index 9df7a455eeb..d84ae9d14d6 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -579,7 +579,7 @@ void TemplateInterpreterGenerator::lock_method() { #ifdef ASSERT { Label L; - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); __ tbnz(Rtemp, JVM_ACC_SYNCHRONIZED_BIT, L); __ stop("method doesn't need synchronization"); __ bind(L); @@ -588,7 +588,7 @@ void TemplateInterpreterGenerator::lock_method() { // get synchronization object { Label done; - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); __ tst(Rtemp, JVM_ACC_STATIC); __ ldr(R0, Address(Rlocals, Interpreter::local_offset_in_bytes(0)), eq); // get receiver (assume this is frequent case) __ b(done, eq); @@ -851,7 +851,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // make sure method is native & not abstract #ifdef ASSERT - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); { Label L; __ tbnz(Rtemp, JVM_ACC_NATIVE_BIT, L); @@ -893,7 +893,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // no synchronization necessary #ifdef ASSERT { Label L; - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); __ tbz(Rtemp, JVM_ACC_SYNCHRONIZED_BIT, L); __ stop("method needs synchronization"); __ bind(L); @@ -975,7 +975,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Pass JNIEnv and mirror for static methods { Label L; - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); __ add(R0, Rthread, in_bytes(JavaThread::jni_environment_offset())); __ tbz(Rtemp, JVM_ACC_STATIC_BIT, L); __ load_mirror(Rtemp, Rmethod, Rtemp); @@ -1204,7 +1204,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // make sure method is not native & not abstract #ifdef ASSERT - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); { Label L; __ tbz(Rtemp, JVM_ACC_NATIVE_BIT, L); @@ -1249,7 +1249,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // no synchronization necessary #ifdef ASSERT { Label L; - __ ldr_u32(Rtemp, Address(Rmethod, Method::access_flags_offset())); + __ ldrh(Rtemp, Address(Rmethod, Method::access_flags_offset())); __ tbz(Rtemp, JVM_ACC_SYNCHRONIZED_BIT, L); __ stop("method needs synchronization"); __ bind(L); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 67b9bdc0414..e097adb1dbf 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -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. * Copyright (c) 2012, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -681,14 +681,14 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, // Check if synchronized method or unlocking prevented by // JavaThread::do_not_unlock_if_synchronized flag. lbz(Rdo_not_unlock_flag, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()), R16_thread); - lwz(Raccess_flags, in_bytes(Method::access_flags_offset()), R19_method); + lhz(Raccess_flags, in_bytes(Method::access_flags_offset()), R19_method); li(R0, 0); stb(R0, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()), R16_thread); // reset flag push(state); // Skip if we don't have to unlock. - rldicl_(R0, Raccess_flags, 64-JVM_ACC_SYNCHRONIZED_BIT, 63); // Extract bit and compare to 0. + testbitdi(CCR0, R0, Raccess_flags, JVM_ACC_SYNCHRONIZED_BIT); beq(CCR0, Lunlocked); cmpwi(CCR0, Rdo_not_unlock_flag, 0); diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index c2e4c2e9b55..bad1a037b9a 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -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. * Copyright (c) 2012, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1202,7 +1202,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label L_skip_barrier; { // Bypass the barrier for non-static methods - __ lwz(R0, in_bytes(Method::access_flags_offset()), R19_method); + __ lhz(R0, in_bytes(Method::access_flags_offset()), R19_method); __ andi_(R0, R0, JVM_ACC_STATIC); __ beq(CCR0, L_skip_barrier); // non-static } diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index 9147dfc1677..ec372bfb07d 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -144,9 +144,9 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { // TODO PPC port: requires change in shared code. //assert(in_bytes(AccessFlags::flags_offset()) == 0, // "MethodDesc._access_flags == MethodDesc._access_flags._flags"); - // _access_flags must be a 32 bit value. - assert(sizeof(AccessFlags) == 4, "wrong size"); - __ lwa(R11_scratch1/*access_flags*/, method_(access_flags)); + // _access_flags must be a 16 bit value. + assert(sizeof(AccessFlags) == 2, "wrong size"); + __ lhz(R11_scratch1/*access_flags*/, method_(access_flags)); // testbit with condition register. __ testbitdi(CCR0, R0, R11_scratch1/*access_flags*/, JVM_ACC_STATIC_BIT); __ btrue(CCR0, L); @@ -823,7 +823,7 @@ void TemplateInterpreterGenerator::lock_method(Register Rflags, Register Rscratc { if (!flags_preloaded) { - __ lwz(Rflags, method_(access_flags)); + __ lhz(Rflags, method_(access_flags)); } #ifdef ASSERT @@ -1301,8 +1301,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { assert(__ nonvolatile_accross_vthread_preemtion(access_flags), "access_flags not preserved"); // Type check. - assert(4 == sizeof(AccessFlags), "unexpected field size"); - __ lwz(access_flags, method_(access_flags)); + assert(2 == sizeof(AccessFlags), "unexpected field size"); + __ lhz(access_flags, method_(access_flags)); // We don't want to reload R19_method and access_flags after calls // to some helper functions. @@ -1769,7 +1769,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef ASSERT else { Label Lok; - __ lwz(R0, in_bytes(Method::access_flags_offset()), R19_method); + __ lhz(R0, in_bytes(Method::access_flags_offset()), R19_method); __ andi_(R0, R0, JVM_ACC_SYNCHRONIZED); __ asm_assert_eq("method needs synchronization"); __ bind(Lok); diff --git a/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp index a864d7073dc..f541ac117eb 100644 --- a/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp +++ b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp @@ -33,6 +33,6 @@ public: void flush_bundle(bool start_new_bundle) {} - static bool supports_shared_stubs() { return false; } + static bool supports_shared_stubs() { return true; } #endif // CPU_RISCV_CODEBUFFER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp b/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp index 7e596e0a7e9..7d5f630d0aa 100644 --- a/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp +++ b/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp @@ -31,7 +31,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size char* result = nullptr; - // RiscV loads a 64-bit immediate in up to four separate steps, splitting it into four different sections + // RISC-V loads a 64-bit immediate in up to four separate steps, splitting it into four different sections // (two 32-bit sections, each split into two subsections of 20/12 bits). // // 63 ....... 44 43 ... 32 31 ....... 12 11 ... 0 @@ -51,11 +51,6 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size // with one instruction (2) result = reserve_address_space_for_unscaled_encoding(size, aslr); - // Failing that, attempt to reserve for base=zero shift>0 - if (result == nullptr && optimize_for_zero_base) { - result = reserve_address_space_for_zerobased_encoding(size, aslr); - } - // Failing that, optimize for case (3) - a base with only bits set between [32-44) if (result == nullptr) { const uintptr_t from = nth_bit(32); diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index e17a3765b50..70fec29d4f7 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -544,7 +544,7 @@ void InterpreterMacroAssembler::remove_activation( // get method access flags ld(x11, Address(fp, frame::interpreter_frame_method_offset * wordSize)); - ld(x12, Address(x11, Method::access_flags_offset())); + load_unsigned_short(x12, Address(x11, Method::access_flags_offset())); test_bit(t0, x12, exact_log2(JVM_ACC_SYNCHRONIZED)); beqz(t0, unlocked); diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 9af1b6a9bb1..12e38d97b13 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -641,7 +641,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label L_skip_barrier; { // Bypass the barrier for non-static methods - __ lwu(t0, Address(xmethod, Method::access_flags_offset())); + __ load_unsigned_short(t0, Address(xmethod, Method::access_flags_offset())); __ test_bit(t1, t0, exact_log2(JVM_ACC_STATIC)); __ beqz(t1, L_skip_barrier); // non-static } diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index bc67de54c4b..a2187b35bd5 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -189,7 +189,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dsin()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_cos : @@ -202,7 +202,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dcos()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_tan : @@ -215,7 +215,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dtan()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_log : @@ -228,7 +228,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_log10 : @@ -241,7 +241,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog10()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_exp : @@ -254,7 +254,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dexp()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_pow : @@ -268,7 +268,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dpow()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_fmaD : @@ -714,14 +714,14 @@ void TemplateInterpreterGenerator::lock_method() { const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); #ifdef ASSERT - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method doesn't need synchronization", false); #endif // ASSERT // get synchronization object { Label done; - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ andi(t0, x10, JVM_ACC_STATIC); // get receiver (assume this is frequent case) __ ld(x10, Address(xlocals, Interpreter::local_offset_in_bytes(0))); @@ -1028,7 +1028,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // make sure method is native & not abstract #ifdef ASSERT - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ verify_access_flags(x10, JVM_ACC_NATIVE, "tried to execute non-native method as native", false); __ verify_access_flags(x10, JVM_ACC_ABSTRACT, "tried to execute abstract method in interpreter"); #endif @@ -1066,7 +1066,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { } else { // no synchronization necessary #ifdef ASSERT - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method needs synchronization"); #endif } @@ -1130,7 +1130,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // pass mirror handle if static call { Label L; - __ lwu(t, Address(xmethod, Method::access_flags_offset())); + __ load_unsigned_short(t, Address(xmethod, Method::access_flags_offset())); __ test_bit(t0, t, exact_log2(JVM_ACC_STATIC)); __ beqz(t0, L); // get mirror @@ -1346,7 +1346,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // do unlocking if necessary { Label L; - __ lwu(t, Address(xmethod, Method::access_flags_offset())); + __ load_unsigned_short(t, Address(xmethod, Method::access_flags_offset())); __ test_bit(t0, t, exact_log2(JVM_ACC_SYNCHRONIZED)); __ beqz(t0, L); // the code below should be shared with interpreter macro @@ -1472,7 +1472,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // make sure method is not native & not abstract #ifdef ASSERT - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ verify_access_flags(x10, JVM_ACC_NATIVE, "tried to execute native method as non-native"); __ verify_access_flags(x10, JVM_ACC_ABSTRACT, "tried to execute abstract method in interpreter"); #endif @@ -1519,7 +1519,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { } else { // no synchronization necessary #ifdef ASSERT - __ lwu(x10, access_flags); + __ load_unsigned_short(x10, access_flags); __ verify_access_flags(x10, JVM_ACC_SYNCHRONIZED, "method needs synchronization"); #endif } diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp index 5e80817aaba..0e31dbd33e1 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.cpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -780,7 +780,7 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, get_method(R_method); verify_oop(Z_tos, state); push(state); // Save tos/result. - testbit(method2_(R_method, access_flags), JVM_ACC_SYNCHRONIZED_BIT); + testbit_ushort(method2_(R_method, access_flags), JVM_ACC_SYNCHRONIZED_BIT); z_bfalse(unlocked); // Don't unlock anything if the _do_not_unlock_if_synchronized flag diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index a069d6ceafb..3647aca0008 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * Copyright 2024 IBM Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -1015,6 +1015,18 @@ void MacroAssembler::load_and_test_long(Register dst, const Address &a) { z_ltg(dst, a); } +// Test a bit in memory for 2 byte datatype. +void MacroAssembler::testbit_ushort(const Address &a, unsigned int bit) { + assert(a.index() == noreg, "no index reg allowed in testbit"); + if (bit <= 7) { + z_tm(a.disp() + 1, a.base(), 1 << bit); + } else if (bit <= 15) { + z_tm(a.disp() + 0, a.base(), 1 << (bit - 8)); + } else { + ShouldNotReachHere(); + } +} + // Test a bit in memory. void MacroAssembler::testbit(const Address &a, unsigned int bit) { assert(a.index() == noreg, "no index reg allowed in testbit"); diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index 15968812818..d45f1321e0f 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * Copyright (c) 2024 IBM Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -199,6 +199,7 @@ class MacroAssembler: public Assembler { // Test a bit in memory. Result is reflected in CC. void testbit(const Address &a, unsigned int bit); + void testbit_ushort(const Address &a, unsigned int bit); // Test a bit in a register. Result is reflected in CC. void testbit(Register r, unsigned int bitPos); diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index 2396a2a7105..62f5c8fa524 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2395,7 +2395,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Label L_skip_barrier; { // Bypass the barrier for non-static methods - __ testbit(Address(Z_method, Method::access_flags_offset()), JVM_ACC_STATIC_BIT); + __ testbit_ushort(Address(Z_method, Method::access_flags_offset()), JVM_ACC_STATIC_BIT); __ z_bfalse(L_skip_barrier); // non-static } diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index 1c4089d5beb..99179bcad06 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -164,7 +164,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { // Therefore add 3 to address that byte within "_flags". // Reload method. VM call above may have destroyed register contents __ get_method(method); - __ testbit(method2_(method, access_flags), JVM_ACC_STATIC_BIT); + __ testbit_ushort(method2_(method, access_flags), JVM_ACC_STATIC_BIT); method = noreg; // end of life __ z_btrue(isStatic); @@ -883,7 +883,7 @@ void TemplateInterpreterGenerator::lock_method(void) { address reentry = nullptr; { Label L; - __ testbit(method2_(method, access_flags), JVM_ACC_SYNCHRONIZED_BIT); + __ testbit_ushort(method2_(method, access_flags), JVM_ACC_SYNCHRONIZED_BIT); __ z_btrue(L); reentry = __ stop_chain_static(reentry, "method doesn't need synchronization"); __ bind(L); @@ -897,7 +897,7 @@ void TemplateInterpreterGenerator::lock_method(void) { Label done; Label static_method; - __ testbit(method2_(method, access_flags), JVM_ACC_STATIC_BIT); + __ testbit_ushort(method2_(method, access_flags), JVM_ACC_STATIC_BIT); __ z_btrue(static_method); // non-static method: Load receiver obj from stack. @@ -1349,15 +1349,17 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Make sure method is native and not abstract. #ifdef ASSERT + // _access_flags must be a 16 bit value. + assert(sizeof(AccessFlags) == 2, "testbit_ushort will fail"); address reentry = nullptr; { Label L; - __ testbit(method_(access_flags), JVM_ACC_NATIVE_BIT); + __ testbit_ushort(method_(access_flags), JVM_ACC_NATIVE_BIT); __ z_btrue(L); reentry = __ stop_chain_static(reentry, "tried to execute non-native method as native"); __ bind(L); } { Label L; - __ testbit(method_(access_flags), JVM_ACC_ABSTRACT_BIT); + __ testbit_ushort(method_(access_flags), JVM_ACC_ABSTRACT_BIT); __ z_bfalse(L); reentry = __ stop_chain_static(reentry, "tried to execute abstract method as non-abstract"); __ bind(L); @@ -1403,7 +1405,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { #ifdef ASSERT { Label L; __ get_method(Z_R1_scratch); - __ testbit(method2_(Z_R1_scratch, access_flags), JVM_ACC_SYNCHRONIZED_BIT); + __ testbit_ushort(method2_(Z_R1_scratch, access_flags), JVM_ACC_SYNCHRONIZED_BIT); __ z_bfalse(L); reentry = __ stop_chain_static(reentry, "method needs synchronization"); __ bind(L); @@ -1461,7 +1463,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Pass mirror handle if static call. { Label method_is_not_static; - __ testbit(method2_(Rmethod, access_flags), JVM_ACC_STATIC_BIT); + __ testbit_ushort(method2_(Rmethod, access_flags), JVM_ACC_STATIC_BIT); __ z_bfalse(method_is_not_static); // Load mirror from interpreter frame. __ z_lg(Z_R1, _z_ijava_state_neg(mirror), Z_fp); @@ -1719,13 +1721,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef ASSERT address reentry = nullptr; { Label L; - __ testbit(method_(access_flags), JVM_ACC_NATIVE_BIT); + __ testbit_ushort(method_(access_flags), JVM_ACC_NATIVE_BIT); __ z_bfalse(L); reentry = __ stop_chain_static(reentry, "tried to execute native method as non-native"); __ bind(L); } { Label L; - __ testbit(method_(access_flags), JVM_ACC_ABSTRACT_BIT); + __ testbit_ushort(method_(access_flags), JVM_ACC_ABSTRACT_BIT); __ z_bfalse(L); reentry = __ stop_chain_static(reentry, "tried to execute abstract method as non-abstract"); __ bind(L); @@ -1775,7 +1777,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef ASSERT { Label L; __ get_method(Z_R1_scratch); - __ testbit(method2_(Z_R1_scratch, access_flags), JVM_ACC_SYNCHRONIZED_BIT); + __ testbit_ushort(method2_(Z_R1_scratch, access_flags), JVM_ACC_SYNCHRONIZED_BIT); __ z_bfalse(L); reentry = __ stop_chain_static(reentry, "method needs synchronization"); __ bind(L); diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index 3a3f01a6409..ff5b1c1454d 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -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 @@ -1030,7 +1030,7 @@ void InterpreterMacroAssembler::remove_activation( // get method access flags movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); - movl(rcx, Address(rcx, Method::access_flags_offset())); + load_unsigned_short(rcx, Address(rcx, Method::access_flags_offset())); testl(rcx, JVM_ACC_SYNCHRONIZED); jcc(Assembler::zero, unlocked); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index ab7cbb94374..b9901a1e95b 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -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 @@ -1099,7 +1099,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm { // Bypass the barrier for non-static methods Register flags = rscratch1; - __ movl(flags, Address(method, Method::access_flags_offset())); + __ load_unsigned_short(flags, Address(method, Method::access_flags_offset())); __ testl(flags, JVM_ACC_STATIC); __ jcc(Assembler::zero, L_skip_barrier); // non-static } diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index 823b965a09b..b4e005faff3 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -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 @@ -596,7 +596,7 @@ void TemplateInterpreterGenerator::lock_method() { #ifdef ASSERT { Label L; - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); __ testl(rax, JVM_ACC_SYNCHRONIZED); __ jcc(Assembler::notZero, L); __ stop("method doesn't need synchronization"); @@ -607,7 +607,7 @@ void TemplateInterpreterGenerator::lock_method() { // get synchronization object { Label done; - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); __ testl(rax, JVM_ACC_STATIC); // get receiver (assume this is frequent case) __ movptr(rax, Address(rlocals, Interpreter::local_offset_in_bytes(0))); @@ -855,7 +855,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // make sure method is native & not abstract #ifdef ASSERT - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); { Label L; __ testl(rax, JVM_ACC_NATIVE); @@ -909,7 +909,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { #ifdef ASSERT { Label L; - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); __ testl(rax, JVM_ACC_SYNCHRONIZED); __ jcc(Assembler::zero, L); __ stop("method needs synchronization"); @@ -999,7 +999,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // pass mirror handle if static call { Label L; - __ movl(t, Address(method, Method::access_flags_offset())); + __ load_unsigned_short(t, Address(method, Method::access_flags_offset())); __ testl(t, JVM_ACC_STATIC); __ jcc(Assembler::zero, L); // get mirror @@ -1280,7 +1280,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // do unlocking if necessary { Label L; - __ movl(t, Address(method, Method::access_flags_offset())); + __ load_unsigned_short(t, Address(method, Method::access_flags_offset())); __ testl(t, JVM_ACC_SYNCHRONIZED); __ jcc(Assembler::zero, L); // the code below should be shared with interpreter macro @@ -1432,7 +1432,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // make sure method is not native & not abstract #ifdef ASSERT - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); { Label L; __ testl(rax, JVM_ACC_NATIVE); @@ -1489,7 +1489,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef ASSERT { Label L; - __ movl(rax, access_flags); + __ load_unsigned_short(rax, access_flags); __ testl(rax, JVM_ACC_SYNCHRONIZED); __ jcc(Assembler::zero, L); __ stop("method needs synchronization"); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index 5ea2d8eba25..b2124c6b157 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -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 @@ -74,7 +74,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { // Do Int register here switch ( i ) { case 0: - __ movl(rscratch1, Address(rbx, Method::access_flags_offset())); + __ load_unsigned_short(rscratch1, Address(rbx, Method::access_flags_offset())); __ testl(rscratch1, JVM_ACC_STATIC); __ cmovptr(Assembler::zero, c_rarg1, Address(rsp, 0)); break; @@ -159,7 +159,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { } // Now handle integrals. Only do c_rarg1 if not static. - __ movl(c_rarg3, Address(rbx, Method::access_flags_offset())); + __ load_unsigned_short(c_rarg3, Address(rbx, Method::access_flags_offset())); __ testl(c_rarg3, JVM_ACC_STATIC); __ cmovptr(Assembler::zero, c_rarg1, Address(rsp, 0)); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 74fdf7a5b76..2df2fbf8adc 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -1337,7 +1337,7 @@ void LIRGenerator::do_getModifiers(Intrinsic* x) { __ cmove(lir_cond_equal, prim_klass, recv_klass, klass, T_ADDRESS); // Get the answer. - __ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_INT), result); + __ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_CHAR), result); } void LIRGenerator::do_getObjectSize(Intrinsic* x) { diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index f102282f682..2133f85ae00 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, 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 @@ -509,12 +509,9 @@ void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) JavaThread* THREAD = current; // For TRAPS processing related to link_shared_classes MetaspaceShared::link_shared_classes(false/*not from jcmd*/, THREAD); if (!HAS_PENDING_EXCEPTION) { - // copy shared path table to saved. - if (!HAS_PENDING_EXCEPTION) { - VM_PopulateDynamicDumpSharedSpace op(archive_name); - VMThread::execute(&op); - return; - } + VM_PopulateDynamicDumpSharedSpace op(archive_name); + VMThread::execute(&op); + return; } // One of the prepatory steps failed diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 753160e7ec1..bd2f0508022 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -987,8 +987,10 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) { ik->external_name()); CLEAR_PENDING_EXCEPTION; SystemDictionaryShared::set_class_has_failed_verification(ik); + } else { + assert(!SystemDictionaryShared::has_class_failed_verification(ik), "sanity"); + ik->compute_has_loops_flag_for_methods(); } - ik->compute_has_loops_flag_for_methods(); BytecodeVerificationLocal = saved; return true; } else { diff --git a/src/hotspot/share/ci/ciFlags.cpp b/src/hotspot/share/ci/ciFlags.cpp index 1401a432a9e..043470a32a2 100644 --- a/src/hotspot/share/ci/ciFlags.cpp +++ b/src/hotspot/share/ci/ciFlags.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, 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 @@ -92,5 +92,5 @@ void ciFlags::print_member_flags(outputStream* st) { // ------------------------------------------------------------------ // ciFlags::print void ciFlags::print(outputStream* st) { - st->print(" flags=%x", _flags); + st->print(" flags=%x", _flags.as_unsigned_short()); } diff --git a/src/hotspot/share/ci/ciFlags.hpp b/src/hotspot/share/ci/ciFlags.hpp index dd1df622487..426f953611f 100644 --- a/src/hotspot/share/ci/ciFlags.hpp +++ b/src/hotspot/share/ci/ciFlags.hpp @@ -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 @@ -26,7 +26,6 @@ #define SHARE_CI_CIFLAGS_HPP #include "ci/ciClassList.hpp" -#include "jvm_constants.h" #include "utilities/accessFlags.hpp" #include "utilities/ostream.hpp" @@ -39,37 +38,37 @@ class ciFlags { friend class ciField; friend class ciMethod; - jint _flags; + AccessFlags _flags; bool _stable; - bool _intialized_final_update; + bool _initialized_final_update; - ciFlags() :_flags(0), _stable(false), _intialized_final_update(false) { } + ciFlags() :_flags(0), _stable(false), _initialized_final_update(false) { } ciFlags(AccessFlags flags, bool is_stable = false, bool is_initialized_final_update = false) : - _flags(flags.as_int()), _stable(is_stable), _intialized_final_update(is_initialized_final_update) { } + _flags(flags), _stable(is_stable), _initialized_final_update(is_initialized_final_update) { } public: // Java access flags - bool is_public () const { return (_flags & JVM_ACC_PUBLIC ) != 0; } - bool is_private () const { return (_flags & JVM_ACC_PRIVATE ) != 0; } - bool is_protected () const { return (_flags & JVM_ACC_PROTECTED ) != 0; } - bool is_static () const { return (_flags & JVM_ACC_STATIC ) != 0; } - bool is_final () const { return (_flags & JVM_ACC_FINAL ) != 0; } - bool is_synchronized () const { return (_flags & JVM_ACC_SYNCHRONIZED ) != 0; } - bool is_super () const { return (_flags & JVM_ACC_SUPER ) != 0; } - bool is_volatile () const { return (_flags & JVM_ACC_VOLATILE ) != 0; } - bool is_transient () const { return (_flags & JVM_ACC_TRANSIENT ) != 0; } - bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; } - bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; } - bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 0; } + bool is_public () const { return _flags.is_public(); } + bool is_private () const { return _flags.is_private(); } + bool is_protected () const { return _flags.is_protected(); } + bool is_static () const { return _flags.is_static(); } + bool is_final () const { return _flags.is_final(); } + bool is_synchronized () const { return _flags.is_synchronized(); } + bool is_super () const { return _flags.is_super(); } + bool is_volatile () const { return _flags.is_volatile(); } + bool is_transient () const { return _flags.is_transient(); } + bool is_native () const { return _flags.is_native(); } + bool is_interface () const { return _flags.is_interface(); } + bool is_abstract () const { return _flags.is_abstract(); } bool is_stable () const { return _stable; } // In case the current object represents a field, return true if // the field is modified outside of instance initializer methods // (or class/initializer methods if the field is static) and false // otherwise. - bool has_initialized_final_update() const { return _intialized_final_update; }; + bool has_initialized_final_update() const { return _initialized_final_update; }; // Conversion - jint as_int() { return _flags; } + jint as_int() { return _flags.as_unsigned_short(); } void print_klass_flags(outputStream* st = tty); void print_member_flags(outputStream* st = tty); diff --git a/src/hotspot/share/ci/ciKlass.cpp b/src/hotspot/share/ci/ciKlass.cpp index f65d4a0311c..e14e237167d 100644 --- a/src/hotspot/share/ci/ciKlass.cpp +++ b/src/hotspot/share/ci/ciKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -222,7 +222,7 @@ jint ciKlass::modifier_flags() { jint ciKlass::access_flags() { assert(is_loaded(), "not loaded"); GUARDED_VM_ENTRY( - return get_Klass()->access_flags().as_int(); + return get_Klass()->access_flags().as_unsigned_short(); ) } diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 5c58f200006..c552e48c8b8 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -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 @@ -2981,7 +2981,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea "Class is both outer and inner class in class file %s", CHECK_0); } // Access flags - jint flags; + u2 flags; // JVM_ACC_MODULE is defined in JDK-9 and later. if (_major_version >= JAVA_9_VERSION) { flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS | JVM_ACC_MODULE); @@ -2998,7 +2998,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea inner_classes->at_put(index++, inner_class_info_index); inner_classes->at_put(index++, outer_class_info_index); inner_classes->at_put(index++, inner_name_index); - inner_classes->at_put(index++, inner_access_flags.as_short()); + inner_classes->at_put(index++, inner_access_flags.as_unsigned_short()); } // Check for circular and duplicate entries. @@ -3750,7 +3750,7 @@ void ClassFileParser::apply_parsed_class_metadata( // Initialize cached modifier_flags to support Class.getModifiers(). // This must follow setting inner_class attributes. - int computed_modifiers = this_klass->compute_modifier_flags(); + u2 computed_modifiers = this_klass->compute_modifier_flags(); this_klass->set_modifier_flags(computed_modifiers); // Delay the setting of _local_interfaces and _transitive_interfaces until after @@ -5336,7 +5336,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, assert(_stream != nullptr, "invariant"); assert(_stream->buffer() == _stream->current(), "invariant"); assert(_class_name != nullptr, "invariant"); - assert(0 == _access_flags.as_int(), "invariant"); + assert(0 == _access_flags.as_unsigned_short(), "invariant"); // Figure out whether we can skip format checking (matching classic VM behavior) _need_verify = Verifier::should_verify_for(_loader_data->class_loader()); @@ -5488,7 +5488,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len // Access flags - jint flags; + u2 flags; // JVM_ACC_MODULE is defined in JDK-9 and later. if (_major_version >= JAVA_9_VERSION) { flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE); diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 1aedb43973c..650d0a9fa74 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -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 @@ -3169,7 +3169,7 @@ void java_lang_ClassFrameInfo::serialize_offsets(SerializeClosure* f) { #endif static int get_flags(const methodHandle& m) { - int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); + int flags = m->access_flags().as_method_flags(); if (m->is_object_initializer()) { flags |= java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR; } else { @@ -5537,7 +5537,7 @@ int InjectedField::compute_offset() { ik->print(); tty->print_cr("all fields:"); for (AllFieldStream fs(ik); !fs.done(); fs.next()) { - tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); + tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_field_flags()); } #endif //PRODUCT vm_exit_during_initialization("Invalid layout of well-known class: use -Xlog:class+load=info to see the origin of the problem class"); diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 407cdafaf20..38226d232ef 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -36,31 +36,31 @@ #include "utilities/tribool.hpp" // These are flag-matching functions: -inline bool match_F_R(jshort flags) { +inline bool match_F_R(u2 flags) { const int req = 0; const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED | JVM_ACC_NATIVE; return (flags & (req | neg)) == req; } -inline bool match_F_Y(jshort flags) { +inline bool match_F_Y(u2 flags) { const int req = JVM_ACC_SYNCHRONIZED; const int neg = JVM_ACC_STATIC | JVM_ACC_NATIVE; return (flags & (req | neg)) == req; } -inline bool match_F_RN(jshort flags) { +inline bool match_F_RN(u2 flags) { const int req = JVM_ACC_NATIVE; const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; return (flags & (req | neg)) == req; } -inline bool match_F_S(jshort flags) { +inline bool match_F_S(u2 flags) { const int req = JVM_ACC_STATIC; const int neg = JVM_ACC_SYNCHRONIZED | JVM_ACC_NATIVE; return (flags & (req | neg)) == req; } -inline bool match_F_SN(jshort flags) { +inline bool match_F_SN(u2 flags) { const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE; const int neg = JVM_ACC_SYNCHRONIZED; return (flags & (req | neg)) == req; @@ -711,7 +711,7 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbolID holder, vmSymbolID name, vmSymbolID sig, - jshort flags) { + u2 flags) { assert((int)vmSymbolID::SID_LIMIT <= (1<inc(time.ticks()); + _peak_compilation_time = MAX2(time.milliseconds(), _peak_compilation_time); + if (!success) { _total_bailout_count++; if (UsePerfData) { @@ -2550,12 +2555,6 @@ void CompileBroker::collect_statistics(CompilerThread* thread, elapsedTimer time _t_invalidated_compilation.add(time); } else { // Compilation succeeded - - // update compilation ticks - used by the implementation of - // java.lang.management.CompilationMXBean - _perf_total_compilation->inc(time.ticks()); - _peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time; - if (CITime) { int bytes_compiled = method->code_size() + task->num_inlined_bytecodes(); if (is_osr) { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 036bc0230c8..31a224597a0 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -383,12 +383,10 @@ class CollectedHeap : public CHeapObj { void increment_total_collections(bool full = false) { _total_collections++; if (full) { - increment_total_full_collections(); + _total_full_collections++; } } - void increment_total_full_collections() { _total_full_collections++; } - // Return the SoftRefPolicy for the heap; SoftRefPolicy* soft_ref_policy() { return &_soft_ref_policy; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp index 4a49d28ea86..c9dbe5f4024 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,7 +74,6 @@ ShenandoahPushWorkerScope::~ShenandoahPushWorkerScope() { } void ShenandoahWorkerThreads::on_create_worker(WorkerThread* worker) { - ShenandoahThreadLocalData::create(worker); if (_initialize_gclab) { ShenandoahThreadLocalData::initialize_gclab(worker); } diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index ca8a85c8bba..507206e2147 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -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 @@ -583,7 +583,7 @@ void LinkResolver::check_method_accessability(Klass* ref_klass, resolved_klass->is_array_klass()) { // We need to change "protected" to "public". assert(flags.is_protected(), "clone not protected?"); - jint new_flags = flags.as_int(); + u2 new_flags = flags.as_method_flags(); new_flags = new_flags & (~JVM_ACC_PROTECTED); new_flags = new_flags | JVM_ACC_PUBLIC; flags.set_flags(new_flags); diff --git a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp index edb87c7fc8e..27b01e99e55 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -72,7 +72,7 @@ const Symbol* EdgeUtils::field_name(const Edge& edge, jshort* modifiers) { JavaFieldStream jfs(ik); while (!jfs.done()) { if (offset == jfs.offset()) { - *modifiers = jfs.access_flags().as_short(); + *modifiers = jfs.access_flags().as_field_flags(); return jfs.name(); } jfs.next(); diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 3b5e24ca9a2..1b85cb1350c 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -46,10 +46,10 @@ $ jfr print dump.jfr Programmatic access: - try (var rf = new RecordingFile(Path.of("dump.jfr)) { + try (var rf = new RecordingFile(Path.of("dump.jfr"))) { while (rf.hasMoreEvents()) { RecordedEvent e = rf.readEvent(); - System.out.println(e.getName() + " " + e.getDuration())); + System.out.println(e.getName() + " " + e.getDuration()); } }; !--> diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index a53eaa474f3..bc5f97c719a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -227,9 +227,9 @@ static traceid method_id(KlassPtr klass, MethodPtr method) { } template -static s4 get_flags(const T* ptr) { +static u2 get_flags(const T* ptr) { assert(ptr != nullptr, "invariant"); - return ptr->access_flags().get_flags(); + return ptr->access_flags().as_unsigned_short(); } // Same as JVM_GetClassModifiers @@ -968,7 +968,7 @@ static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leak writer->write(artifact_id(klass)); writer->write(mark_symbol(method->name(), leakp)); writer->write(mark_symbol(method->signature(), leakp)); - writer->write(static_cast(get_flags(method))); + writer->write(get_flags(method)); writer->write(get_visibility(method)); return 1; } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 9052e622894..1fa3f23173c 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, 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 @@ -1000,7 +1000,7 @@ C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, ARGUMENT_PA if (info.is_null() || JVMCIENV->get_length(info) != 4) { JVMCI_ERROR_NULL("info must not be null and have a length of 4"); } - JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int()); + JVMCIENV->put_int_at(info, 0, fd.access_flags().as_field_flags()); JVMCIENV->put_int_at(info, 1, fd.offset()); JVMCIENV->put_int_at(info, 2, fd.index()); JVMCIENV->put_int_at(info, 3, fd.field_flags().as_uint()); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 712745e2a02..1a53f6b6d2c 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -1592,7 +1592,7 @@ JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) { HotSpotJVMCI::FieldInfo::set_nameIndex(JVMCIENV, obj_h(), (jint)fieldinfo->name_index()); HotSpotJVMCI::FieldInfo::set_signatureIndex(JVMCIENV, obj_h(), (jint)fieldinfo->signature_index()); HotSpotJVMCI::FieldInfo::set_offset(JVMCIENV, obj_h(), (jint)fieldinfo->offset()); - HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_int()); + HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_field_flags()); HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint()); HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index()); return wrap(obj_h()); @@ -1603,7 +1603,7 @@ JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) { (jint)fieldinfo->name_index(), (jint)fieldinfo->signature_index(), (jint)fieldinfo->offset(), - (jint)fieldinfo->access_flags().as_int(), + (jint)fieldinfo->access_flags().as_field_flags(), (jint)fieldinfo->field_flags().as_uint(), (jint)fieldinfo->initializer_index()); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index ba47e559957..97447c43b6e 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -273,7 +273,7 @@ nonstatic_field(Klass, _name, Symbol*) \ volatile_nonstatic_field(Klass, _next_sibling, Klass*) \ nonstatic_field(Klass, _java_mirror, OopHandle) \ - nonstatic_field(Klass, _modifier_flags, jint) \ + nonstatic_field(Klass, _modifier_flags, u2) \ nonstatic_field(Klass, _access_flags, AccessFlags) \ nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \ nonstatic_field(Klass, _secondary_supers_bitmap, uintx) \ @@ -488,7 +488,6 @@ declare_constant(InvocationEntryBci) \ declare_constant(JVMCINMethodData::SPECULATION_LENGTH_BITS) \ \ - declare_constant(JVM_ACC_WRITTEN_FLAGS) \ declare_constant(FieldInfo::FieldFlags::_ff_injected) \ declare_constant(FieldInfo::FieldFlags::_ff_stable) \ declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \ diff --git a/src/hotspot/share/logging/logDecorators.cpp b/src/hotspot/share/logging/logDecorators.cpp index 6c06bd45716..019c2fcb36c 100644 --- a/src/hotspot/share/logging/logDecorators.cpp +++ b/src/hotspot/share/logging/logDecorators.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -100,7 +100,9 @@ bool LogDecorators::parse(const char* decorator_args, outputStream* errstream) { break; } tmp_decorators |= mask(d); - token = comma_pos + 1; + if (comma_pos != nullptr) { + token = comma_pos + 1; + } } while (comma_pos != nullptr); os::free(args_copy); if (result) { diff --git a/src/hotspot/share/logging/logSelection.cpp b/src/hotspot/share/logging/logSelection.cpp index 99ecc9f87f2..f5a0ab1bf53 100644 --- a/src/hotspot/share/logging/logSelection.cpp +++ b/src/hotspot/share/logging/logSelection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -151,7 +151,9 @@ static LogSelection parse_internal(char *str, outputStream* errstream) { return LogSelection::Invalid; } tags[ntags++] = tag; - cur_tag = plus_pos + 1; + if (plus_pos != nullptr) { + cur_tag = plus_pos + 1; + } } while (plus_pos != nullptr); for (size_t i = 0; i < ntags; i++) { diff --git a/src/hotspot/share/logging/logSelectionList.cpp b/src/hotspot/share/logging/logSelectionList.cpp index ac63f20512c..d7e5981aa00 100644 --- a/src/hotspot/share/logging/logSelectionList.cpp +++ b/src/hotspot/share/logging/logSelectionList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -69,7 +69,7 @@ bool LogSelectionList::parse(const char* str, outputStream* errstream) { } char* copy = os::strdup_check_oom(str, mtLogging); // Split string on commas - for (char *comma_pos = copy, *cur = copy; success && comma_pos != nullptr; cur = comma_pos + 1) { + for (char *comma_pos = copy, *cur = copy; success; cur = comma_pos + 1) { if (_nselections == MaxSelections) { if (errstream != nullptr) { errstream->print_cr("Can not have more than " SIZE_FORMAT " log selections in a single configuration.", @@ -90,6 +90,10 @@ bool LogSelectionList::parse(const char* str, outputStream* errstream) { break; } _selections[_nselections++] = selection; + + if (comma_pos == nullptr) { + break; + } } os::free(copy); diff --git a/src/hotspot/share/oops/fieldInfo.cpp b/src/hotspot/share/oops/fieldInfo.cpp index 50a3b427d17..3ae91a03b67 100644 --- a/src/hotspot/share/oops/fieldInfo.cpp +++ b/src/hotspot/share/oops/fieldInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ void FieldInfo::print(outputStream* os, ConstantPool* cp) { name_index(), name(cp)->as_utf8(), signature_index(), signature(cp)->as_utf8(), offset(), - access_flags().as_int(), + access_flags().as_field_flags(), field_flags().as_uint(), initializer_index(), generic_signature_index(), @@ -97,7 +97,7 @@ Array* FieldInfoStream::create_FieldInfoStream(GrowableArray* fie assert(fi_ref->name_index() == fi.name_index(), "Must be"); assert(fi_ref->signature_index() == fi.signature_index(), "Must be"); assert(fi_ref->offset() == fi.offset(), "Must be"); - assert(fi_ref->access_flags().as_int() == fi.access_flags().as_int(), "Must be"); + assert(fi_ref->access_flags().as_field_flags() == fi.access_flags().as_field_flags(), "Must be"); assert(fi_ref->field_flags().as_uint() == fi.field_flags().as_uint(), " Must be"); if(fi_ref->field_flags().is_initialized()) { assert(fi_ref->initializer_index() == fi.initializer_index(), "Must be"); diff --git a/src/hotspot/share/oops/fieldInfo.inline.hpp b/src/hotspot/share/oops/fieldInfo.inline.hpp index 2e6727f1fb9..bf37d280510 100644 --- a/src/hotspot/share/oops/fieldInfo.inline.hpp +++ b/src/hotspot/share/oops/fieldInfo.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -73,7 +73,7 @@ inline void Mapper::map_field_info(const FieldInfo& fi) { _consumer->accept_uint(fi.name_index()); _consumer->accept_uint(fi.signature_index()); _consumer->accept_uint(fi.offset()); - _consumer->accept_uint(fi.access_flags().as_int()); + _consumer->accept_uint(fi.access_flags().as_field_flags()); _consumer->accept_uint(fi.field_flags().as_uint()); if(fi.field_flags().has_any_optionals()) { if (fi.field_flags().is_initialized()) { diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index ce46da55f98..43b078a8af2 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -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 @@ -3339,8 +3339,8 @@ InstanceKlass* InstanceKlass::compute_enclosing_class(bool* inner_is_member, TRA return outer_klass; } -jint InstanceKlass::compute_modifier_flags() const { - jint access = access_flags().as_int(); +u2 InstanceKlass::compute_modifier_flags() const { + u2 access = access_flags().as_unsigned_short(); // But check if it happens to be member class. InnerClassesIterator iter(this); @@ -3360,7 +3360,7 @@ jint InstanceKlass::compute_modifier_flags() const { } } // Remember to strip ACC_SUPER bit - return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS; + return (access & (~JVM_ACC_SUPER)); } jint InstanceKlass::jvmti_class_status() const { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 8209a692a82..cedc17e9baf 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -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 @@ -391,7 +391,7 @@ class InstanceKlass: public Klass { public: int field_offset (int index) const { return field(index).offset(); } - int field_access_flags(int index) const { return field(index).access_flags().as_int(); } + int field_access_flags(int index) const { return field(index).access_flags().as_field_flags(); } FieldInfo::FieldFlags field_flags(int index) const { return field(index).field_flags(); } FieldStatus field_status(int index) const { return fields_status()->at(index); } inline Symbol* field_name (int index) const; @@ -682,8 +682,6 @@ class InstanceKlass: public Klass { #if INCLUDE_JVMTI // Redefinition locking. Class can only be redefined by one thread at a time. - // The flag is in access_flags so that it can be set and reset using atomic - // operations, and not be reset by other misc_flag settings. bool is_being_redefined() const { return _misc_flags.is_being_redefined(); } void set_is_being_redefined(bool value) { _misc_flags.set_is_being_redefined(value); } @@ -1127,7 +1125,7 @@ class InstanceKlass: public Klass { void compute_has_loops_flag_for_methods(); #endif - jint compute_modifier_flags() const; + u2 compute_modifier_flags() const; public: // JVMTI support diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 2c75d6da3b8..d27665bbcc1 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -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 @@ -66,7 +66,7 @@ class Klass : public Metadata { friend class JVMCIVMStructs; public: // Klass Kinds for all subclasses of Klass - enum KlassKind { + enum KlassKind : u2 { InstanceKlassKind, InstanceRefKlassKind, InstanceMirrorKlassKind, @@ -113,15 +113,20 @@ class Klass : public Metadata { // // Final note: This comes first, immediately after C++ vtable, // because it is frequently queried. - jint _layout_helper; + jint _layout_helper; // Klass kind used to resolve the runtime type of the instance. // - Used to implement devirtualized oop closure dispatching. // - Various type checking in the JVM const KlassKind _kind; + AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. + // Some flags created by the JVM, not in the class file itself, + // are in _misc_flags below. // Processed access flags, for use by Class.getModifiers. - jint _modifier_flags; + u2 _modifier_flags; + + KlassFlags _misc_flags; // The fields _super_check_offset, _secondary_super_cache, _secondary_supers // and _primary_supers all help make fast subtype checks. See big discussion @@ -157,22 +162,12 @@ class Klass : public Metadata { // Provide access the corresponding instance java.lang.ClassLoader. ClassLoaderData* _class_loader_data; + markWord _prototype_header; // Used to initialize objects' header + // Bitmap and hash code used by hashed secondary supers. uintx _secondary_supers_bitmap; uint8_t _hash_slot; - markWord _prototype_header; // Used to initialize objects' header - - int _vtable_len; // vtable length. This field may be read very often when we - // have lots of itable dispatches (e.g., lambdas and streams). - // Keep it away from the beginning of a Klass to avoid cacheline - // contention that may happen when a nearby object is modified. - AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. - // Some flags created by the JVM, not in the class file itself, - // are in _misc_flags below. - - JFR_ONLY(DEFINE_TRACE_ID_FIELD;) - private: // This is an index into FileMapHeader::_shared_path_table[], to // associate this class with the JAR file where it's loaded from during @@ -200,10 +195,17 @@ class Klass : public Metadata { }; #endif - KlassFlags _misc_flags; + int _vtable_len; // vtable length. This field may be read very often when we + // have lots of itable dispatches (e.g., lambdas and streams). + // Keep it away from the beginning of a Klass to avoid cacheline + // contention that may happen when a nearby object is modified. CDS_JAVA_HEAP_ONLY(int _archived_mirror_index;) +public: + + JFR_ONLY(DEFINE_TRACE_ID_FIELD;) + protected: Klass(KlassKind kind); @@ -292,8 +294,8 @@ class Klass : public Metadata { void clear_java_mirror_handle() { _java_mirror = OopHandle(); } // modifier flags - jint modifier_flags() const { return _modifier_flags; } - void set_modifier_flags(jint flags) { _modifier_flags = flags; } + u2 modifier_flags() const { return _modifier_flags; } + void set_modifier_flags(u2 flags) { _modifier_flags = flags; } // size helper int layout_helper() const { return _layout_helper; } @@ -756,7 +758,7 @@ class Klass : public Metadata { virtual void release_C_heap_structures(bool release_constant_pool = true); public: - virtual jint compute_modifier_flags() const = 0; + virtual u2 compute_modifier_flags() const = 0; // JVMTI support virtual jint jvmti_class_status() const; diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index 1e1b8d77a90..9cb46f4697d 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -188,7 +188,7 @@ class markWord { static markWord INFLATING() { return zero(); } // inflate-in-progress // Should this header be preserved during GC? - bool must_be_preserved(const oopDesc* obj) const { + bool must_be_preserved() const { return (!is_unlocked() || !has_no_hash()); } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index d0b29a4a309..ab15379409f 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -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 @@ -1652,8 +1652,8 @@ void Method::init_intrinsic_id(vmSymbolID klass_id) { && sig_id == vmSymbolID::NO_SID) { return; } - jshort flags = access_flags().as_short(); + u2 flags = access_flags().as_method_flags(); vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); if (id != vmIntrinsics::_none) { set_intrinsic_id(id); @@ -2300,7 +2300,7 @@ void Method::print_on(outputStream* st) const { st->print (" - method holder: "); method_holder()->print_value_on(st); st->cr(); st->print (" - constants: " PTR_FORMAT " ", p2i(constants())); constants()->print_value_on(st); st->cr(); - st->print (" - access: 0x%x ", access_flags().as_int()); access_flags().print_on(st); st->cr(); + st->print (" - access: 0x%x ", access_flags().as_method_flags()); access_flags().print_on(st); st->cr(); st->print (" - flags: 0x%x ", _flags.as_int()); _flags.print_on(st); st->cr(); st->print (" - name: "); name()->print_value_on(st); st->cr(); st->print (" - signature: "); signature()->print_value_on(st); st->cr(); diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 271d8b39863..7b13337ecaf 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -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 @@ -75,8 +75,8 @@ class Method : public Metadata { MethodData* _method_data; MethodCounters* _method_counters; AdapterHandlerEntry* _adapter; - AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) + AccessFlags _access_flags; // Access flags MethodFlags _flags; u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index 04bc374e522..903c5660d53 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -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 @@ -341,12 +341,12 @@ void ObjArrayKlass::metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_bottom_klass); } -jint ObjArrayKlass::compute_modifier_flags() const { +u2 ObjArrayKlass::compute_modifier_flags() const { // The modifier for an objectArray is the same as its element assert (element_klass() != nullptr, "should be initialized"); // Return the flags of the bottom element type. - jint element_flags = bottom_klass()->compute_modifier_flags(); + u2 element_flags = bottom_klass()->compute_modifier_flags(); return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED)) | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL); diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp index e16f1f2eb0f..c44c8d28f62 100644 --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -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 @@ -143,7 +143,7 @@ class ObjArrayKlass : public ArrayKlass { inline void oop_oop_iterate_elements_bounded(objArrayOop a, OopClosureType* closure, void* low, void* high); public: - jint compute_modifier_flags() const; + u2 compute_modifier_flags() const; public: // Printing diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index 45902e63147..9ce953380ba 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -452,7 +452,7 @@ bool oopDesc::mark_must_be_preserved() const { } bool oopDesc::mark_must_be_preserved(markWord m) const { - return m.must_be_preserved(this); + return m.must_be_preserved(); } #endif // SHARE_OOPS_OOP_INLINE_HPP diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp index 8ca6a49fc46..86c4f9d7138 100644 --- a/src/hotspot/share/oops/typeArrayKlass.cpp +++ b/src/hotspot/share/oops/typeArrayKlass.cpp @@ -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 @@ -75,7 +75,7 @@ TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType return new (loader_data, size, THREAD) TypeArrayKlass(type, name); } -jint TypeArrayKlass::compute_modifier_flags() const { +u2 TypeArrayKlass::compute_modifier_flags() const { return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } diff --git a/src/hotspot/share/oops/typeArrayKlass.hpp b/src/hotspot/share/oops/typeArrayKlass.hpp index 9dc3ed607fe..6ec72ae49c0 100644 --- a/src/hotspot/share/oops/typeArrayKlass.hpp +++ b/src/hotspot/share/oops/typeArrayKlass.hpp @@ -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 @@ -73,7 +73,7 @@ class TypeArrayKlass : public ArrayKlass { // Copying void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS); - jint compute_modifier_flags() const; + u2 compute_modifier_flags() const; // Oop iterators. Since there are no oops in TypeArrayKlasses, // these functions only return the size of the object. diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 40b19eecd9f..56cfb9fe16e 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -3871,7 +3871,7 @@ Node* LibraryCallKit::generate_klass_flags_guard(Node* kls, int modifier_mask, i } Node* LibraryCallKit::generate_interface_guard(Node* kls, RegionNode* region) { return generate_klass_flags_guard(kls, JVM_ACC_INTERFACE, 0, region, - Klass::access_flags_offset(), TypeInt::INT, T_INT); + Klass::access_flags_offset(), TypeInt::CHAR, T_CHAR); } // Use this for testing if Klass is_hidden, has_finalizer, and is_cloneable_fast. @@ -3904,8 +3904,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { break; case vmIntrinsics::_getModifiers: prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); - assert(is_power_of_2((int)JVM_ACC_WRITTEN_FLAGS+1), "change next line"); - return_type = TypeInt::make(0, JVM_ACC_WRITTEN_FLAGS, Type::WidenMin); + return_type = TypeInt::CHAR; break; case vmIntrinsics::_isInterface: prim_return_value = intcon(0); @@ -3927,7 +3926,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { break; case vmIntrinsics::_getClassAccessFlags: prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); - return_type = TypeInt::INT; // not bool! 6297094 + return_type = TypeInt::CHAR; break; default: fatal_unexpected_iid(id); @@ -3988,7 +3987,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { case vmIntrinsics::_getModifiers: p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); - query_value = make_load(nullptr, p, TypeInt::INT, T_INT, MemNode::unordered); + query_value = make_load(nullptr, p, TypeInt::CHAR, T_CHAR, MemNode::unordered); break; case vmIntrinsics::_isInterface: @@ -4053,7 +4052,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { case vmIntrinsics::_getClassAccessFlags: p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); - query_value = make_load(nullptr, p, TypeInt::INT, T_INT, MemNode::unordered); + query_value = make_load(nullptr, p, TypeInt::CHAR, T_CHAR, MemNode::unordered); break; default: diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index ad351fb81ad..78ffbe05ae4 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -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. * Copyright (c) 2024, Alibaba Group Holding Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1976,24 +1976,24 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, if (tkls->offset() == in_bytes(Klass::modifier_flags_offset())) { // The field is Klass::_modifier_flags. Return its (constant) value. // (Folds up the 2nd indirection in aClassConstant.getModifiers().) - assert(this->Opcode() == Op_LoadI, "must load an int from _modifier_flags"); + assert(Opcode() == Op_LoadUS, "must load an unsigned short from _modifier_flags"); return TypeInt::make(klass->modifier_flags()); } if (tkls->offset() == in_bytes(Klass::access_flags_offset())) { // The field is Klass::_access_flags. Return its (constant) value. // (Folds up the 2nd indirection in Reflection.getClassAccessFlags(aClassConstant).) - assert(this->Opcode() == Op_LoadI, "must load an int from _access_flags"); + assert(Opcode() == Op_LoadUS, "must load an unsigned short from _access_flags"); return TypeInt::make(klass->access_flags()); } if (tkls->offset() == in_bytes(Klass::misc_flags_offset())) { // The field is Klass::_misc_flags. Return its (constant) value. // (Folds up the 2nd indirection in Reflection.getClassAccessFlags(aClassConstant).) - assert(this->Opcode() == Op_LoadUB, "must load an unsigned byte from _misc_flags"); + assert(Opcode() == Op_LoadUB, "must load an unsigned byte from _misc_flags"); return TypeInt::make(klass->misc_flags()); } if (tkls->offset() == in_bytes(Klass::layout_helper_offset())) { // The field is Klass::_layout_helper. Return its constant value if known. - assert(this->Opcode() == Op_LoadI, "must load an int from _layout_helper"); + assert(Opcode() == Op_LoadI, "must load an int from _layout_helper"); return TypeInt::make(klass->layout_helper()); } diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 50ae1deecbf..101006d9afc 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -345,7 +345,7 @@ class Node { // The PhaseRenumberLive phase renumbers nodes based on liveness information. // Therefore, it updates the value of the _idx field. The parse-time _idx is // preserved in _parse_idx. - const node_idx_t _idx; + node_idx_t _idx; DEBUG_ONLY(const node_idx_t _parse_idx;) // IGV node identifier. Two nodes, possibly in different compilation phases, // have the same IGV identifier if (and only if) they are the very same node @@ -586,8 +586,7 @@ class Node { // Set this node's index, used by cisc_version to replace current node void set_idx(uint new_idx) { - const node_idx_t* ref = &_idx; - *(node_idx_t*)ref = new_idx; + _idx = new_idx; } // Swap input edge order. (Edge indexes i1 and i2 are usually 1 and 2.) void swap_edges(uint i1, uint i2) { diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 33429dfacad..e62524b37cd 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -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 @@ -666,7 +666,7 @@ VectorNode* VectorNode::make_mask_node(int vopc, Node* n1, Node* n2, uint vlen, } } -// Make a vector node for binary operation +// Make a vector node for unary or binary operation VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, bool is_mask, bool is_var_shift, bool is_unsigned) { // This method should not be called for unimplemented vectors. guarantee(vopc > 0, "vopc must be > 0"); @@ -747,6 +747,9 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b case Op_URShiftVI: return new URShiftVINode(n1, n2, vt, is_var_shift); case Op_URShiftVL: return new URShiftVLNode(n1, n2, vt, is_var_shift); + case Op_LShiftCntV: return new LShiftCntVNode(n1, vt); + case Op_RShiftCntV: return new RShiftCntVNode(n1, vt); + case Op_AndV: return new AndVNode(n1, n2, vt); case Op_OrV: return new OrVNode (n1, n2, vt); case Op_XorV: return new XorVNode(n1, n2, vt); @@ -766,6 +769,18 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b case Op_SaturatingAddV: return new SaturatingAddVNode(n1, n2, vt, is_unsigned); case Op_SaturatingSubV: return new SaturatingSubVNode(n1, n2, vt, is_unsigned); + case Op_VectorCastB2X: return new VectorCastB2XNode(n1, vt); + case Op_VectorCastS2X: return new VectorCastS2XNode(n1, vt); + case Op_VectorCastI2X: return new VectorCastI2XNode(n1, vt); + case Op_VectorCastL2X: return new VectorCastL2XNode(n1, vt); + case Op_VectorCastF2X: return new VectorCastF2XNode(n1, vt); + case Op_VectorCastD2X: return new VectorCastD2XNode(n1, vt); + case Op_VectorUCastB2X: return new VectorUCastB2XNode(n1, vt); + case Op_VectorUCastS2X: return new VectorUCastS2XNode(n1, vt); + case Op_VectorUCastI2X: return new VectorUCastI2XNode(n1, vt); + case Op_VectorCastHF2F: return new VectorCastHF2FNode(n1, vt); + case Op_VectorCastF2HF: return new VectorCastF2HFNode(n1, vt); + default: fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); return nullptr; @@ -791,6 +806,7 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, Node* n3, const TypeV case Op_SelectFromTwoVector: return new SelectFromTwoVectorNode(n1, n2, n3, vt); case Op_SignumVD: return new SignumVDNode(n1, n2, n3, vt); case Op_SignumVF: return new SignumVFNode(n1, n2, n3, vt); + case Op_VectorBlend: return new VectorBlendNode(n1, n2, n3); default: fatal("Missed vector creation for '%s'", NodeClassNames[vopc]); return nullptr; @@ -818,22 +834,26 @@ VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, BasicType bt, bool is_ } VectorNode* VectorNode::shift_count(int opc, Node* cnt, uint vlen, BasicType bt) { - // Match shift count type with shift vector type. + int vopc = VectorNode::shift_count_opcode(opc); const TypeVect* vt = TypeVect::make(bt, vlen); + return VectorNode::make(vopc, cnt, nullptr, vt); +} + +int VectorNode::shift_count_opcode(int opc) { switch (opc) { case Op_LShiftI: case Op_LShiftL: - return new LShiftCntVNode(cnt, vt); + return Op_LShiftCntV; case Op_RShiftI: case Op_RShiftL: case Op_URShiftB: case Op_URShiftS: case Op_URShiftI: case Op_URShiftL: - return new RShiftCntVNode(cnt, vt); + return Op_RShiftCntV; default: - fatal("Missed vector creation for '%s'", NodeClassNames[opc]); - return nullptr; + fatal("Node class '%s' is not supported for shift count", NodeClassNames[opc]); + return -1; } } @@ -1412,24 +1432,9 @@ VectorStoreMaskNode* VectorStoreMaskNode::make(PhaseGVN& gvn, Node* in, BasicTyp return new VectorStoreMaskNode(in, gvn.intcon(elem_size), vt); } -VectorCastNode* VectorCastNode::make(int vopc, Node* n1, BasicType bt, uint vlen) { +VectorNode* VectorCastNode::make(int vopc, Node* n1, BasicType bt, uint vlen) { const TypeVect* vt = TypeVect::make(bt, vlen); - switch (vopc) { - case Op_VectorCastB2X: return new VectorCastB2XNode(n1, vt); - case Op_VectorCastS2X: return new VectorCastS2XNode(n1, vt); - case Op_VectorCastI2X: return new VectorCastI2XNode(n1, vt); - case Op_VectorCastL2X: return new VectorCastL2XNode(n1, vt); - case Op_VectorCastF2X: return new VectorCastF2XNode(n1, vt); - case Op_VectorCastD2X: return new VectorCastD2XNode(n1, vt); - case Op_VectorUCastB2X: return new VectorUCastB2XNode(n1, vt); - case Op_VectorUCastS2X: return new VectorUCastS2XNode(n1, vt); - case Op_VectorUCastI2X: return new VectorUCastI2XNode(n1, vt); - case Op_VectorCastHF2F: return new VectorCastHF2FNode(n1, vt); - case Op_VectorCastF2HF: return new VectorCastF2HFNode(n1, vt); - default: - assert(false, "unknown node: %s", NodeClassNames[vopc]); - return nullptr; - } + return VectorNode::make(vopc, n1, nullptr, vt); } int VectorCastNode::opcode(int sopc, BasicType bt, bool is_signed) { diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index f5574ba79e3..0bd1c71d7e6 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -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 @@ -95,6 +95,8 @@ class VectorNode : public TypeNode { static int opcode(int sopc, BasicType bt); // scalar_opc -> vector_opc static int scalar_opcode(int vopc, BasicType bt); // vector_opc -> scalar_opc + static int shift_count_opcode(int opc); + // Limits on vector size (number of elements) for auto-vectorization. static bool vector_size_supported_auto_vectorization(const BasicType bt, int size); static bool implemented(int opc, uint vlen, BasicType bt); @@ -1764,7 +1766,7 @@ class VectorCastNode : public VectorNode { VectorCastNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} virtual int Opcode() const; - static VectorCastNode* make(int vopc, Node* n1, BasicType bt, uint vlen); + static VectorNode* make(int vopc, Node* n1, BasicType bt, uint vlen); static int opcode(int opc, BasicType bt, bool is_signed = true); static bool implemented(int opc, uint vlen, BasicType src_type, BasicType dst_type); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 12c7898f4cf..198165cdd1e 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -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 @@ -1306,7 +1306,7 @@ JVM_ENTRY(jint, JVM_GetClassModifiers(JNIEnv *env, jclass cls)) } Klass* k = java_lang_Class::as_Klass(mirror); - debug_only(int computed_modifiers = k->compute_modifier_flags()); + debug_only(u2 computed_modifiers = k->compute_modifier_flags()); assert(k->modifier_flags() == computed_modifiers, "modifiers cache is OK"); return k->modifier_flags(); JVM_END @@ -1817,7 +1817,7 @@ JVM_ENTRY(jint, JVM_GetClassAccessFlags(JNIEnv *env, jclass cls)) } Klass* k = java_lang_Class::as_Klass(mirror); - return k->access_flags().as_int() & JVM_ACC_WRITTEN_FLAGS; + return k->access_flags().as_class_flags(); } JVM_END @@ -2460,14 +2460,14 @@ JVM_ENTRY(jint, JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_ind Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); Method* method = InstanceKlass::cast(k)->methods()->at(method_index); - return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; + return method->access_flags().as_method_flags(); JVM_END JVM_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)) Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - return InstanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS; + return InstanceKlass::cast(k)->field_access_flags(field_index); JVM_END @@ -2657,7 +2657,7 @@ JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, j InstanceKlass* ik = InstanceKlass::cast(k_called); for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { if (fs.name() == name && fs.signature() == signature) { - return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS; + return fs.access_flags().as_field_flags(); } } return -1; @@ -2686,7 +2686,7 @@ JVM_ENTRY(jint, JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, for (int i = 0; i < methods_count; i++) { Method* method = methods->at(i); if (method->name() == name && method->signature() == signature) { - return method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; + return method->access_flags().as_method_flags(); } } return -1; diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index 0afbf56b3fc..e8e127486ca 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -1218,7 +1218,7 @@ jvmtiEnv *jvmti;

  • Timed wait? diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index ceed1d8ad95..10fb4121472 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -85,7 +85,7 @@ void JvmtiClassFileReconstituter::write_field_infos() { // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } - write_u2(access_flags.get_flags() & JVM_RECOGNIZED_FIELD_MODIFIERS); + write_u2(access_flags.as_field_flags()); write_u2(name_index); write_u2(signature_index); u2 attr_count = 0; @@ -704,7 +704,7 @@ void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) return; } - write_u2(access_flags.get_flags() & JVM_RECOGNIZED_METHOD_MODIFIERS); + write_u2(access_flags.as_method_flags()); write_u2(const_method->name_index()); write_u2(const_method->signature_index()); @@ -919,7 +919,7 @@ void JvmtiClassFileReconstituter::write_class_file_format() { copy_cpool_bytes(writeable_address(cpool_size())); // JVMSpec| u2 access_flags; - write_u2(ik()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS); + write_u2(ik()->access_flags().as_class_flags()); // JVMSpec| u2 this_class; // JVMSpec| u2 super_class; diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 554b4baf7b2..e97bfc30042 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -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 @@ -3149,7 +3149,7 @@ jvmtiError JvmtiEnv::GetFieldModifiers(fieldDescriptor* fdesc_ptr, jint* modifiers_ptr) { AccessFlags resultFlags = fdesc_ptr->access_flags(); - jint result = resultFlags.as_int(); + jint result = resultFlags.as_field_flags(); *modifiers_ptr = result; return JVMTI_ERROR_NONE; @@ -3228,7 +3228,7 @@ JvmtiEnv::GetMethodDeclaringClass(Method* method, jclass* declaring_class_ptr) { jvmtiError JvmtiEnv::GetMethodModifiers(Method* method, jint* modifiers_ptr) { NULL_CHECK(method, JVMTI_ERROR_INVALID_METHODID); - (*modifiers_ptr) = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; + (*modifiers_ptr) = method->access_flags().as_method_flags(); return JVMTI_ERROR_NONE; } /* end GetMethodModifiers */ diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index a982ac97c47..0a53eadbbd8 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -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 @@ -1005,8 +1005,8 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( } // Check whether class modifiers are the same. - jushort old_flags = (jushort) the_class->access_flags().get_flags(); - jushort new_flags = (jushort) scratch_class->access_flags().get_flags(); + u2 old_flags = the_class->access_flags().as_class_flags(); + u2 new_flags = scratch_class->access_flags().as_class_flags(); if (old_flags != new_flags) { log_info(redefine, class, normalize) ("redefined class %s modifiers change error: modifiers changed from %d to %d.", @@ -1040,9 +1040,9 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // access - old_flags = old_fs.access_flags().as_short(); - new_flags = new_fs.access_flags().as_short(); - if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { + old_flags = old_fs.access_flags().as_field_flags(); + new_flags = new_fs.access_flags().as_field_flags(); + if (old_flags != new_flags) { log_info(redefine, class, normalize) ("redefined class %s field %s change error: modifiers changed from %d to %d.", the_class->external_name(), name_sym2->as_C_string(), old_flags, new_flags); @@ -1147,8 +1147,8 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( switch (method_was) { case matched: // methods match, be sure modifiers do too - old_flags = (jushort) k_old_method->access_flags().get_flags(); - new_flags = (jushort) k_new_method->access_flags().get_flags(); + old_flags = k_old_method->access_flags().as_method_flags(); + new_flags = k_new_method->access_flags().as_method_flags(); if ((old_flags ^ new_flags) & ~(JVM_ACC_NATIVE)) { log_info(redefine, class, normalize) ("redefined class %s method %s modifiers error: modifiers changed from %d to %d", diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 1e44ea95731..5b406828510 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -239,7 +239,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { assert(m.not_null(), "null method handle"); InstanceKlass* m_klass = m->method_holder(); assert(m_klass != nullptr, "null holder for method handle"); - int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); + int flags = (m->access_flags().as_method_flags()); int vmindex = Method::invalid_vtable_index; LogTarget(Debug, methodhandles, indy) lt_indy; @@ -352,7 +352,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) { InstanceKlass* ik = fd.field_holder(); - int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); + int flags = fd.access_flags().as_field_flags(); flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT); if (fd.is_trusted_final()) flags |= TRUSTED_FINAL; if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT); @@ -404,7 +404,7 @@ bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) { Method* m = iklass->find_method(name, poly_sig); if (m != nullptr) { int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS; - int flags = m->access_flags().as_int(); + int flags = m->access_flags().as_method_flags(); if ((flags & required) == required) { return true; } @@ -417,7 +417,7 @@ bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) { for (; ms < me; ms++) { Method* m = iklass->methods()->at(ms); int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS; - int flags = m->access_flags().as_int(); + int flags = m->access_flags().as_method_flags(); if ((flags & required) == required && ArgumentCount(m->signature()).size() == 1) { return true; } @@ -522,7 +522,7 @@ bool MethodHandles::is_signature_polymorphic_public_name(Klass* klass, Symbol* n for (; ms < me; ms++) { Method* m = iklass->methods()->at(ms); int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS | JVM_ACC_PUBLIC; - int flags = m->access_flags().as_int(); + int flags = m->access_flags().as_method_flags(); if ((flags & required) == required && ArgumentCount(m->signature()).size() == 1) { return true; } diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index a4b1d0ece6d..01038b879ab 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -920,14 +920,19 @@ WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject metho if (compLevel < CompLevel_none || compLevel > CompilationPolicy::highest_compile_level()) { return false; // Intrinsic is not available on a non-existent compilation level. } + AbstractCompiler* comp = CompileBroker::compiler((int)compLevel); + if (comp == nullptr) { + // Could have compLevel == 0, or !TieredCompilation and incompatible values of TieredStopAtLevel and compLevel. + tty->print_cr("WB error: no compiler for requested compilation level %d", compLevel); + return false; + } + jmethodID method_id, compilation_context_id; method_id = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id)); DirectiveSet* directive; - AbstractCompiler* comp = CompileBroker::compiler((int)compLevel); - assert(comp != nullptr, "compiler not available"); if (compilation_context != nullptr) { compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context); CHECK_JNI_EXCEPTION_(env, JNI_FALSE); diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 0029a555d26..61e1e0d20b7 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1162,10 +1162,7 @@ void frame::oops_do_internal(OopClosure* f, NMethodClosure* cf, const RegisterMap* map, bool use_interpreter_oop_map_cache) const { #ifndef PRODUCT // simulate GC crash here to dump java thread in error report - if (CrashGCForDumpingJavaThread) { - char *t = nullptr; - *t = 'c'; - } + guarantee(!CrashGCForDumpingJavaThread, ""); #endif if (is_interpreted_frame()) { oops_interpreted_do(f, map, use_interpreter_oop_map_cache); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index f9f3c4e1458..9c73e255db2 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -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 @@ -971,7 +971,7 @@ static void print_hex_location(outputStream* st, const_address p, int unitsize, const uint64_t value = LITTLE_ENDIAN_ONLY((((uint64_t)i2) << 32) | i1) BIG_ENDIAN_ONLY((((uint64_t)i1) << 32) | i2); - st->print("%016" FORMAT64_MODIFIER "x", value); + st->print(UINT64_FORMAT_0, value); print_ascii_form(ascii_form, value, unitsize); } else { st->print_raw("????????????????"); @@ -995,7 +995,7 @@ static void print_hex_location(outputStream* st, const_address p, int unitsize, case 1: st->print("%02x", (u1)value); break; case 2: st->print("%04x", (u2)value); break; case 4: st->print("%08x", (u4)value); break; - case 8: st->print("%016" FORMAT64_MODIFIER "x", (u8)value); break; + case 8: st->print(UINT64_FORMAT_0, (u8)value); break; } print_ascii_form(ascii_form, value, unitsize); } else { diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp index 7739cff03bf..3aef7028a79 100644 --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -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 @@ -778,7 +778,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac Handle name = Handle(THREAD, name_oop); if (name == nullptr) return nullptr; - const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; + const int modifiers = method->access_flags().as_method_flags(); Handle mh = java_lang_reflect_Method::create(CHECK_NULL); @@ -819,7 +819,7 @@ oop Reflection::new_constructor(const methodHandle& method, TRAPS) { objArrayHandle exception_types = get_exception_types(method, CHECK_NULL); assert(!exception_types.is_null(), "cannot return null"); - const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; + const int modifiers = method->access_flags().as_method_flags(); Handle ch = java_lang_reflect_Constructor::create(CHECK_NULL); @@ -859,7 +859,7 @@ oop Reflection::new_field(fieldDescriptor* fd, TRAPS) { java_lang_reflect_Field::set_trusted_final(rh()); } // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here. - java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); + java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_field_flags()); java_lang_reflect_Field::set_override(rh(), false); if (fd->has_generic_signature()) { Symbol* gs = fd->generic_signature(); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 941309ca2ac..fdce6d21531 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -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 @@ -1264,36 +1264,49 @@ static bool monitors_used_above_threshold(MonitorList* list) { if (MonitorUsedDeflationThreshold == 0) { // disabled case is easy return false; } - // Start with ceiling based on a per-thread estimate: - size_t ceiling = ObjectSynchronizer::in_use_list_ceiling(); - size_t old_ceiling = ceiling; - if (ceiling < list->max()) { - // The max used by the system has exceeded the ceiling so use that: - ceiling = list->max(); - } size_t monitors_used = list->count(); if (monitors_used == 0) { // empty list is easy return false; } - if (NoAsyncDeflationProgressMax != 0 && - _no_progress_cnt >= NoAsyncDeflationProgressMax) { - double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; - size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1; - ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); - log_info(monitorinflation)("Too many deflations without progress; " - "bumping in_use_list_ceiling from " SIZE_FORMAT - " to " SIZE_FORMAT, old_ceiling, new_ceiling); - _no_progress_cnt = 0; - ceiling = new_ceiling; - } + size_t old_ceiling = ObjectSynchronizer::in_use_list_ceiling(); + // Make sure that we use a ceiling value that is not lower than + // previous, not lower than the recorded max used by the system, and + // not lower than the current number of monitors in use (which can + // race ahead of max). The result is guaranteed > 0. + size_t ceiling = MAX3(old_ceiling, list->max(), monitors_used); // Check if our monitor usage is above the threshold: size_t monitor_usage = (monitors_used * 100LL) / ceiling; if (int(monitor_usage) > MonitorUsedDeflationThreshold) { + // Deflate monitors if over the threshold percentage, unless no + // progress on previous deflations. + bool is_above_threshold = true; + + // Check if it's time to adjust the in_use_list_ceiling up, due + // to too many async deflation attempts without any progress. + if (NoAsyncDeflationProgressMax != 0 && + _no_progress_cnt >= NoAsyncDeflationProgressMax) { + double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; + size_t delta = (size_t)(ceiling * remainder) + 1; + size_t new_ceiling = (ceiling > SIZE_MAX - delta) + ? SIZE_MAX // Overflow, let's clamp new_ceiling. + : ceiling + delta; + + ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); + log_info(monitorinflation)("Too many deflations without progress; " + "bumping in_use_list_ceiling from " SIZE_FORMAT + " to " SIZE_FORMAT, old_ceiling, new_ceiling); + _no_progress_cnt = 0; + ceiling = new_ceiling; + + // Check if our monitor usage is still above the threshold: + monitor_usage = (monitors_used * 100LL) / ceiling; + is_above_threshold = int(monitor_usage) > MonitorUsedDeflationThreshold; + } log_info(monitorinflation)("monitors_used=" SIZE_FORMAT ", ceiling=" SIZE_FORMAT ", monitor_usage=" SIZE_FORMAT ", threshold=%d", monitors_used, ceiling, monitor_usage, MonitorUsedDeflationThreshold); - return true; + return is_above_threshold; } return false; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index f5cb2805c8e..b6e54575519 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -263,7 +263,7 @@ nonstatic_field(Klass, _secondary_supers, Array*) \ nonstatic_field(Klass, _primary_supers[0], Klass*) \ nonstatic_field(Klass, _java_mirror, OopHandle) \ - nonstatic_field(Klass, _modifier_flags, jint) \ + nonstatic_field(Klass, _modifier_flags, u2) \ nonstatic_field(Klass, _super, Klass*) \ volatile_nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ @@ -1017,7 +1017,7 @@ nonstatic_field(vframeArrayElement, _bci, int) \ nonstatic_field(vframeArrayElement, _method, Method*) \ \ - nonstatic_field(AccessFlags, _flags, jint) \ + nonstatic_field(AccessFlags, _flags, u2) \ nonstatic_field(elapsedTimer, _counter, jlong) \ nonstatic_field(elapsedTimer, _active, bool) \ nonstatic_field(InvocationCounter, _counter, unsigned int) \ diff --git a/src/hotspot/share/utilities/accessFlags.cpp b/src/hotspot/share/utilities/accessFlags.cpp index ec68d124488..fc11491174f 100644 --- a/src/hotspot/share/utilities/accessFlags.cpp +++ b/src/hotspot/share/utilities/accessFlags.cpp @@ -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 @@ -47,5 +47,5 @@ void AccessFlags::print_on(outputStream* st) const { #endif // !PRODUCT || INCLUDE_JVMTI void accessFlags_init() { - assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags"); + assert(sizeof(AccessFlags) == sizeof(u2), "just checking size of flags"); } diff --git a/src/hotspot/share/utilities/accessFlags.hpp b/src/hotspot/share/utilities/accessFlags.hpp index 74ccbd20ac1..a752c09cb42 100644 --- a/src/hotspot/share/utilities/accessFlags.hpp +++ b/src/hotspot/share/utilities/accessFlags.hpp @@ -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 @@ -30,28 +30,19 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -// AccessFlags is an abstraction over Java access flags. +// AccessFlags is an abstraction over Java ACC flags. +// See generated file classfile_constants.h for shared JVM_ACC_XXX access flags class outputStream; -enum { - // See jvm.h for shared JVM_ACC_XXX access flags - - // flags actually put in .class file - JVM_ACC_WRITTEN_FLAGS = 0x00007FFF, - - // Do not add new ACC flags here. -}; - - class AccessFlags { friend class VMStructs; private: - jint _flags; // TODO: move 4 access flags above to Klass and change to u2 + u2 _flags; public: AccessFlags() : _flags(0) {} - explicit AccessFlags(jint flags) : _flags(flags) {} + explicit AccessFlags(u2 flags) : _flags(flags) {} // Java access flags bool is_public () const { return (_flags & JVM_ACC_PUBLIC ) != 0; } @@ -70,15 +61,10 @@ class AccessFlags { // Attribute flags bool is_synthetic () const { return (_flags & JVM_ACC_SYNTHETIC ) != 0; } - // get .class file flags - jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } + // get as integral value + u2 as_unsigned_short() const { return _flags; } - // Initialization - void set_field_flags(jint flags) { - assert((flags & JVM_RECOGNIZED_FIELD_MODIFIERS) == flags, "only recognized flags"); - _flags = (flags & JVM_RECOGNIZED_FIELD_MODIFIERS); - } - void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); } + void set_flags(u2 flags) { _flags = flags; } private: friend class Klass; @@ -90,11 +76,22 @@ class AccessFlags { void set_is_synthetic() { _flags |= JVM_ACC_SYNTHETIC; } public: - // Conversion - jshort as_short() const { return (jshort)_flags; } - jint as_int() const { return _flags; } + inline friend AccessFlags accessFlags_from(u2 flags); - inline friend AccessFlags accessFlags_from(jint flags); + u2 as_method_flags() const { + assert((_flags & JVM_RECOGNIZED_METHOD_MODIFIERS) == _flags, "only recognized flags"); + return _flags; + } + + u2 as_field_flags() const { + assert((_flags & JVM_RECOGNIZED_FIELD_MODIFIERS) == _flags, "only recognized flags"); + return _flags; + } + + u2 as_class_flags() const { + assert((_flags & JVM_RECOGNIZED_CLASS_MODIFIERS) == _flags, "only recognized flags"); + return _flags; + } // Printing/debugging #if INCLUDE_JVMTI @@ -104,7 +101,7 @@ class AccessFlags { #endif }; -inline AccessFlags accessFlags_from(jint flags) { +inline AccessFlags accessFlags_from(u2 flags) { AccessFlags af; af._flags = flags; return af; diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index ce864119d75..86bee7a071f 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -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 @@ -99,6 +99,7 @@ class oopDesc; // _X_0 - print as hexadecimal, with leading 0s: 0x00012345 // _W(w) - prints w sized string with the given value right // adjusted. Use -w to print left adjusted. +// _0 - print as hexadecimal, with leading 0s, without 0x prefix: 0012345 // // Note that the PTR format specifiers print using 0x with leading zeros, // just like the _X_0 version for integers. @@ -131,6 +132,7 @@ class oopDesc; #define UINT64_FORMAT_X "0x%" PRIx64 #define UINT64_FORMAT_X_0 "0x%016" PRIx64 #define UINT64_FORMAT_W(width) "%" #width PRIu64 +#define UINT64_FORMAT_0 "%016" PRIx64 // Format integers which change size between 32- and 64-bit. #define SSIZE_FORMAT "%" PRIdPTR diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp index 863e588d180..a2fbc3be363 100644 --- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp @@ -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 @@ -90,17 +90,6 @@ inline int g_isfinite(jfloat f) { return isfinite(f); } inline int g_isfinite(jdouble f) { return isfinite(f); } -// Formatting. -#ifdef _LP64 -# ifdef __APPLE__ -# define FORMAT64_MODIFIER "ll" -# else -# define FORMAT64_MODIFIER "l" -# endif -#else // !_LP64 -#define FORMAT64_MODIFIER "ll" -#endif // _LP64 - // gcc warns about applying offsetof() to non-POD object or calculating // offset directly when base address is null. The -Wno-invalid-offsetof // option could be used to suppress this warning, but we instead just diff --git a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp index 3f22948118d..83d07557287 100644 --- a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp @@ -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 @@ -103,9 +103,6 @@ inline int g_isnan(jdouble f) { return _isnan(f); } inline int g_isfinite(jfloat f) { return _finite(f); } inline int g_isfinite(jdouble f) { return _finite(f); } -// Formatting. -#define FORMAT64_MODIFIER "ll" - #define offset_of(klass,field) offsetof(klass,field) #define THREAD_LOCAL __declspec(thread) diff --git a/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java b/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java index 4f5bda557c6..b8610655b6c 100644 --- a/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java +++ b/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012 SAP SE. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -26,15 +26,17 @@ package sun.nio.ch; -import java.nio.channels.spi.AsynchronousChannelProvider; -import sun.nio.ch.Pollset; +import java.io.FileDescriptor; import java.io.IOException; -import java.util.HashSet; -import java.util.Iterator; +import java.nio.channels.spi.AsynchronousChannelProvider; import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.RejectedExecutionException; +import java.util.HashSet; +import java.util.Iterator; +import sun.nio.ch.IOUtil; +import sun.nio.ch.Pollset; /** * AsynchronousChannelGroup implementation based on the AIX pollset framework. @@ -141,6 +143,8 @@ static class ControlEvent { sv = new int[2]; try { Pollset.socketpair(sv); + // make the reading part of the socket nonblocking, so the drain (drain_all) method works + IOUtil.configureBlocking(IOUtil.newFD(sv[0]), false); // register one end with pollset Pollset.pollsetCtl(pollset, Pollset.PS_ADD, sv[0], Net.POLLIN); } catch (IOException x) { @@ -271,23 +275,21 @@ private void queueControlEvent(ControlEvent ev) { // Process all events currently stored in the control queue. private void processControlQueue() { - synchronized (controlQueue) { - // On Aix it is only possible to set the event - // bits on the first call of pollsetCtl. Later - // calls only add bits, but cannot remove them. - // Therefore, we always remove the file - // descriptor ignoring the error and then add it. - Iterator iter = controlQueue.iterator(); - while (iter.hasNext()) { - ControlEvent ev = iter.next(); - Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, ev.fd(), 0); - if (!ev.removeOnly()) { - ev.setError(Pollset.pollsetCtl(pollset, Pollset.PS_MOD, ev.fd(), ev.events())); - } - iter.remove(); + // On Aix it is only possible to set the event + // bits on the first call of pollsetCtl. Later + // calls only add bits, but cannot remove them. + // Therefore, we always remove the file + // descriptor ignoring the error and then add it. + Iterator iter = controlQueue.iterator(); + while (iter.hasNext()) { + ControlEvent ev = iter.next(); + Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, ev.fd(), 0); + if (!ev.removeOnly()) { + ev.setError(Pollset.pollsetCtl(pollset, Pollset.PS_MOD, ev.fd(), ev.events())); } - controlQueue.notifyAll(); + iter.remove(); } + controlQueue.notifyAll(); } /* @@ -306,8 +308,21 @@ private Event poll() throws IOException { int n; controlLock.lock(); try { - n = Pollset.pollsetPoll(pollset, address, + int m; + m = n = Pollset.pollsetPoll(pollset, address, MAX_EVENTS_TO_POLL, Pollset.PS_NO_TIMEOUT); + while (m-- > 0) { + long eventAddress = Pollset.getEvent(address, m); + int fd = Pollset.getDescriptor(eventAddress); + + // To emulate one shot semantic we need to remove + // the file descriptor here. + if (fd != sp[0] && fd != ctlSp[0]) { + synchronized (controlQueue) { + Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, fd, 0); + } + } + } } finally { controlLock.unlock(); } @@ -323,14 +338,6 @@ private Event poll() throws IOException { long eventAddress = Pollset.getEvent(address, n); int fd = Pollset.getDescriptor(eventAddress); - // To emulate one shot semantic we need to remove - // the file descriptor here. - if (fd != sp[0] && fd != ctlSp[0]) { - synchronized (controlQueue) { - Pollset.pollsetCtl(pollset, Pollset.PS_DELETE, fd, 0); - } - } - // wakeup if (fd == sp[0]) { if (wakeupCount.decrementAndGet() == 0) { @@ -350,7 +357,7 @@ private Event poll() throws IOException { // wakeup to process control event if (fd == ctlSp[0]) { synchronized (controlQueue) { - Pollset.drain1(ctlSp[0]); + IOUtil.drain(ctlSp[0]); processControlQueue(); } if (n > 0) { diff --git a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java index 1608e77bee6..ab246a8653b 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -25,7 +25,9 @@ package java.lang.classfile; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.constantpool.ConstantPool; +import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.LoadableConstantEntry; import java.lang.classfile.constantpool.MethodHandleEntry; import java.util.List; @@ -34,10 +36,20 @@ /** * Models an entry in the bootstrap method table. The bootstrap method table - * is stored in the {@code BootstrapMethods} attribute, but is modeled by - * the {@link ConstantPool}, since the bootstrap method table is logically - * part of the constant pool. + * is stored in the {@link BootstrapMethodsAttribute BootstrapMethods} + * attribute, but is modeled by the {@link ConstantPool}, since the bootstrap + * method table is logically part of the constant pool. + *

    + * A bootstrap method entry is composite: + * {@snippet lang=text : + * // @link substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(MethodHandleEntry, List)" : + * BootstrapMethodEntry( + * MethodHandleEntry bootstrapMethod, // @link substring="bootstrapMethod" target="#bootstrapMethod" + * List arguments // @link substring="arguments" target="#arguments()" + * ) + * } * + * @see ConstantPoolBuilder#bsmEntry ConstantPoolBuilder::bsmEntry * @since 24 */ public sealed interface BootstrapMethodEntry @@ -45,11 +57,19 @@ public sealed interface BootstrapMethodEntry /** * {@return the constant pool associated with this entry} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * BootstrapMethodEntry} {@code entry}, use {@link + * ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry is compatible. */ ConstantPool constantPool(); /** - * {@return the index into the bootstrap method table corresponding to this entry} + * {@return the index into the bootstrap method table corresponding to this + * entry} */ int bsmIndex(); diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index c98991ecf7a..43fb1927b38 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -140,21 +140,56 @@ static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyReso /** * Option describing whether to preserve the original constant pool when - * transforming a classfile. Reusing the constant pool enables significant - * optimizations in processing time and minimizes differences between the - * original and transformed classfile, but may result in a bigger classfile - * when a classfile is significantly transformed. - * Default is {@code SHARED_POOL} to preserve the original constant - * pool. + * transforming a {@code class} file. Reusing the constant pool enables + * significant optimizations in processing time and minimizes differences + * between the original and transformed {@code class} files, but may result + * in a bigger transformed {@code class} file when many elements of the + * original {@code class} file are dropped and many original constant + * pool entries become unused. Default is {@link #SHARED_POOL} to preserve + * the original constant pool. * + * @see ConstantPoolBuilder + * @see #build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see #transformClass(ClassModel, ClassTransform) * @since 24 */ enum ConstantPoolSharingOption implements Option { - /** Preserves the original constant pool when transforming classfile */ + /** + * Preserves the original constant pool when transforming the {@code + * class} file. + *

    + * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.SHARED_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(originalClass), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel) + */ SHARED_POOL, - /** Creates a new constant pool when transforming classfile */ + /** + * Creates a new constant pool when transforming the {@code class} file. + *

    + * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.NEW_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of() ConstantPoolBuilder::of() + */ NEW_POOL } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java index 5255ceb1ef7..c4b6546fe20 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -28,10 +28,9 @@ import java.lang.constant.ConstantDesc; /** - * A constant pool entry that may be used by annotation constant values, - * which includes the four kinds of primitive constants and UTF8 constants. - * These entries are also the only entries that do not refer to other - * constant pool entries. + * Marker interface for constant pool entries that can represent constant values + * associated with elements of annotations. They are also the only entries that + * do not refer to other constant pool entries. * * @apiNote * An annotation constant value entry alone is not sufficient to determine @@ -40,6 +39,7 @@ * in {@link AnnotationValue.OfInt}. * * @see AnnotationValue.OfConstant + * @jvms 4.7.16.1 The {@code element_value} structure * @sealedGraph * @since 24 */ @@ -47,9 +47,9 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, Utf8Entry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double} for the primitive constants, - * or {@link String} for UTF8 constants. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@link Long}, {@link Float}, {@link Double} for the primitive + * constants, or {@link String} for UTF8 constants. */ ConstantDesc constantValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java index 2a3bd95da22..5017838d68e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,33 +30,82 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Class_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.1 The CONSTANT_Class_info Structure + * Models a {@code CONSTANT_Class_info} structure, representing a reference + * type, in the constant pool of a {@code class} file. + *

    + * The use of a {@code ClassEntry} is modeled by a {@link ClassDesc} that is not + * primitive. Conversions are through {@link ConstantPoolBuilder#classEntry( + * ClassDesc)} and {@link #asSymbol()}. + *

    + * A {@code ClassEntry} is composite: + * {@snippet lang=text : + * // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(Utf8Entry)" : + * ClassEntry(Utf8Entry name) // @link substring="name" target="#name" + * } + * where {@code name} represents: + *

      + *
    • The internal form of a binary name (JVMS {@jvms 4.2.1}), if and only if + * this {@code ClassEntry} represents a class or interface, such as {@code + * java/lang/String} for the {@link String} class. + *
    • A field descriptor string (JVMS {@jvms 4.3.2}) representing an array type, + * if and only if this {@code ClassEntry} represents an array type, such as + * {@code [I} for the {@code int[]} type, or {@code [Ljava/lang/String;} for the + * {@code String[]} type. + *
    + * A field descriptor string for an array type can be distinguished by its + * leading {@code '['} character. * + * @apiNote + * The internal form of a binary name, where all occurrences of {@code .} in the + * name are replaced by {@code /}, is informally known as an {@index + * "internal name"}. This concept also applies to package names in + * addition to class and interface names. + * + * @see ConstantPoolBuilder#classEntry ConstantPoolBuilder::classEntry + * @see ClassDesc + * @jvms 4.4.1 The {@code CONSTANT_Class_info} Structure * @since 24 */ public sealed interface ClassEntry extends LoadableConstantEntry permits AbstractPoolEntry.ClassEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the UTF8 constant pool entry for the class name} + * {@return the {@code Utf8Entry} referred by this structure} If the + * value of the UTF8 starts with a {@code [}, this represents an array type + * and the value is a descriptor string; otherwise, this represents a class + * or interface and the value is the {@linkplain ##internalname internal + * form} of a binary name. + * + * @see ConstantPoolBuilder#classEntry(Utf8Entry) + * ConstantPoolBuilder::classEntry(Utf8Entry) */ Utf8Entry name(); /** - * {@return the class name, as an internal binary name} + * {@return the represented reference type, as the {@linkplain + * ##internalname internal form} of a binary name or an array descriptor + * string} This is a shortcut for {@link #name() name().stringValue()}. */ String asInternalName(); /** - * {@return the class name, as a symbolic descriptor} + * {@return the represented reference type, as a symbolic descriptor} The + * returned descriptor is never {@linkplain ClassDesc#isPrimitive() + * primitive}. + * + * @see ConstantPoolBuilder#classEntry(ClassDesc) + * ConstantPoolBuilder::classEntry(ClassDesc) */ ClassDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java index 72050cd9b8f..bbd03c88292 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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,10 +33,36 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_Dynamic_info} structure, representing a {@index + * "dynamically-computed constant"}, in the constant pool of a {@code + * class} file. + *

    + * The use of a {@code ConstantDynamicEntry} is modeled by a {@link + * DynamicConstantDesc}. Conversions are through {@link #asSymbol()} and {@link + * ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)}. + *

    + * A dynamic constant entry is composite: + * {@snippet lang=text : + * // @link substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * ConstantDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where {@link #type() nameAndType.type()} is a {@linkplain #typeSymbol() + * field descriptor} string. * + * @apiNote + * A dynamically-computed constant is frequently called a {@index "dynamic + * constant"}, or a {@index "condy"}, from the abbreviation of + * "constant dynamic". + * + * @see ConstantPoolBuilder#constantDynamicEntry + * ConstantPoolBuilder::constantDynamicEntry + * @see DynamicConstantDesc + * @see java.lang.invoke##condycon Dynamically-computed constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface ConstantDynamicEntry @@ -44,19 +70,28 @@ public sealed interface ConstantDynamicEntry permits AbstractPoolEntry.ConstantDynamicEntryImpl { /** - * {@return a symbolic descriptor for the dynamic constant's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type} of + * this dynamically-computed constant} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); } + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the symbolic descriptor for the {@code invokedynamic} constant} + * {@return a symbolic descriptor for this dynamically-computed constant} + * + * @see ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc) + * ConstantPoolBuilder::constantDynamicEntry(DynamicConstantDesc) */ default DynamicConstantDesc asSymbol() { return DynamicConstantDesc.ofNamed(bootstrap().bootstrapMethod().asSymbol(), @@ -68,10 +103,15 @@ default DynamicConstantDesc asSymbol() { } /** - * {@return the type of the constant} + * {@inheritDoc} + * + * @apiNote + * The data type of a dynamically-computed constant depends on its + * {@linkplain #type() descriptor}, while the data type of all other + * constants can be determined by their {@linkplain #tag() constant type}. */ @Override default TypeKind typeKind() { - return TypeKind.fromDescriptor(type().stringValue()); + return TypeKind.fromDescriptor(type()); } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java index 91dc8906b7b..6fed8dad8b7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -27,14 +27,22 @@ import java.lang.classfile.BootstrapMethodEntry; import java.lang.classfile.ClassReader; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.util.Iterator; import java.util.NoSuchElementException; /** - * Provides read access to the constant pool and bootstrap method table of a - * classfile. - * @jvms 4.4 The Constant Pool + * Provides read access to the constant pool and the bootstrap method table of a + * {@code class} file. + * + *

    Index in the Constant Pool

    + * The constant pool entries are accessed by index. A valid index is in the + * range of {@link #size() [1, size())}. It is {@linkplain PoolEntry#width() + * unusable} if a {@link LongEntry} or {@link DoubleEntry} is at its previous + * index. * + * @see BootstrapMethodsAttribute + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -46,7 +54,7 @@ public sealed interface ConstantPool extends Iterable * * @apiNote * If only a particular type of entry is expected, use {@link #entryByIndex( - * int, Class) entryByIndex(int, Class)}. + * int, Class)}. * * @param index the index within the pool of the desired entry * @throws ConstantPoolException if the index is out of range of the @@ -55,7 +63,11 @@ public sealed interface ConstantPool extends Iterable PoolEntry entryByIndex(int index); /** - * {@return the size of the constant pool} + * {@return the exclusive upper bound of the valid indices of this constant + * pool} The actual number of entries is lower because {@code 0}, {@code + * size()} are not valid, and a valid index may be unusable. + * + * @see ##index Index in the Constant Pool */ int size(); @@ -66,12 +78,17 @@ public sealed interface ConstantPool extends Iterable * @param index the index within the pool of the desired entry * @param cls the entry type * @throws ConstantPoolException if the index is out of range of the - * constant pool, or the entry is not of the given type + * constant pool or considered unusable, or the entry is not + * of the given type */ T entryByIndex(int index, Class cls); /** * {@return an iterator over pool entries} + * + * @apiNote + * This skips any unusable index and is less error-prone than iterating by + * raw index. See {@linkplain ##index Index in the Constant Pool}. */ @Override default Iterator iterator() { @@ -93,7 +110,6 @@ public PoolEntry next() { }; } - /** * {@return the {@link BootstrapMethodEntry} at the specified index within * the bootstrap method table} diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index 2dc2a390bd1..260fc982dab 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -25,10 +25,16 @@ package java.lang.classfile.constantpool; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; import java.lang.classfile.ClassModel; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.attribute.ConstantValueAttribute; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.*; +import java.lang.invoke.MethodHandleInfo; import java.util.List; +import java.util.function.Consumer; import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl; import jdk.internal.classfile.impl.ClassReaderImpl; @@ -39,14 +45,45 @@ import static java.util.Objects.requireNonNull; /** - * Builder for the constant pool of a classfile. Provides read and write access - * to the constant pool that is being built. Writing is append-only and idempotent - * (entry-bearing methods will return an existing entry if there is one). + * Builder for the constant pool of a {@code class} file. Provides read and + * write access to the constant pool that is {@linkplain ClassFileBuilder#constantPool() + * being built}. Writing is append-only (the index of new entries monotonically + * increase) and idempotent (entry-bearing methods will return an existing entry + * if there is a suitable one). + *

    + * For {@code class} file building, an overload of {@link ClassFile#build( + * ClassEntry, ConstantPoolBuilder, Consumer) ClassFile::build} takes a + * {@code ConstantPoolBuilder}. For {@code class} file transformations via + * {@link ClassFile#transformClass ClassFile::transformClass}, the {@link + * ClassFile.ConstantPoolSharingOption} controls how the constant pool builder + * of the resulting {@code class} is created. * - * A {@linkplain ConstantPoolBuilder} is associated with a {@link ClassBuilder}. - * The {@linkplain ConstantPoolBuilder} also provides access to some of the - * state of the {@linkplain ClassBuilder}, such as classfile processing options. + *

    Alien Constant Pool Entries

    + * In {@code class} file building and constant pool building, some constant pool + * entries supplied may be {@linkplain #canWriteDirect(ConstantPool) alien} + * to this constant pool builder of the active class file builder. For example, + * {@link #classEntry(Utf8Entry) classEntry(Utf8Entry)} may be called with an + * alien UTF8 entry. Alien entries will be converted to a pool entry in + * this constant pool builder, reusing equivalent entries or adding new entries + * if there is none. As a result, all pool entries returned by entry-bearing + * methods in this constant pool builder belong to this constant pool. + *

    + * Some {@link ClassFileBuilder} methods may have their outputs adjusted if they + * receive pool entries alien to {@linkplain ClassFileBuilder#constantPool + * their constant pools}. For example, if an {@link ConstantInstruction#ofLoad + * ldc_w} instruction with an alien entry is written to a {@link CodeBuilder}, + * the {@code CodeBuilder} may emit a functionally equivalent {@code ldc} + * instruction instead, if the converted entry can be encoded in such an + * instruction. + *

    + * To avoid the conversion of alien constant pool entries, such as for the + * accuracy of the generated {@code class} file, users can always supply + * constant pool entries obtained by calling the constant pool builder + * entry-bearing methods of the constant pools associated with the {@code + * ClassFileBuilder}. Otherwise, the conversions have no impact on the + * behaviors of the generated {@code class} files. * + * @see ClassFileBuilder#constantPool() * @since 24 */ public sealed interface ConstantPoolBuilder @@ -55,10 +92,14 @@ public sealed interface ConstantPoolBuilder /** * {@return a new constant pool builder} The new constant pool builder will - * be pre-populated with the contents of the constant pool associated with - * the class reader. + * be pre-populated with the contents of the constant pool {@linkplain + * ClassModel#constantPool() associated with} the given class model. The + * index of new entries will start from the {@link ConstantPool#size() + * size()} of the source pool. * * @param classModel the class to copy from + * @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see ClassFile.ConstantPoolSharingOption#SHARED_POOL */ static ConstantPoolBuilder of(ClassModel classModel) { return new SplitConstantPool((ClassReaderImpl) classModel.constantPool()); @@ -66,35 +107,47 @@ static ConstantPoolBuilder of(ClassModel classModel) { /** * {@return a new constant pool builder} The new constant pool builder - * will be empty. + * will be empty. The index of new entries will start from {@code 1}. + * + * @see ClassFile.ConstantPoolSharingOption#NEW_POOL */ static ConstantPoolBuilder of() { return new SplitConstantPool(); } /** - * {@return whether the provided constant pool is index-compatible with this - * one} This may be because they are the same constant pool, or because this - * constant pool was copied from the other. + * {@return {@code true} if the index of any entry in the given constant + * pool refers to the same entry in this builder} This may be because they + * are the same builder, or because this builder was {@linkplain + * #of(ClassModel) pre-populated} from the given constant pool. + *

    + * If the constant pool of an entry is not directly writable to this pool, + * it is alien to this pool, and a {@link ClassFileBuilder} associated + * with this constant pool will convert that alien constant pool entry. * - * @param constantPool the other constant pool + * @param constantPool the given constant pool + * @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool + * @see ##alien Alien Constant Pool Entries */ boolean canWriteDirect(ConstantPool constantPool); /** - * {@return A {@link Utf8Entry} describing the provided {@linkplain String}} - * If a UTF8 entry in the pool already describes this string, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the provided {@link String}} * * @param s the string + * @see Utf8Entry#stringValue() Utf8Entry::stringValue */ Utf8Entry utf8Entry(String s); /** - * {@return A {@link Utf8Entry} describing the field descriptor of the provided - * {@linkplain ClassDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * ClassDesc#descriptorString() field descriptor string} of the provided + * {@link ClassDesc}} + * + * @apiNote + * The resulting {@code Utf8Entry} is usually not {@linkplain + * #classEntry(Utf8Entry) referable by} a {@link ClassEntry}, which uses + * internal form of binary names. * * @param desc the symbolic descriptor for the class */ @@ -103,10 +156,9 @@ default Utf8Entry utf8Entry(ClassDesc desc) { } /** - * {@return A {@link Utf8Entry} describing the method descriptor of the provided - * {@linkplain MethodTypeDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * MethodTypeDesc#descriptorString() method descriptor string} of the + * provided {@link MethodTypeDesc}} * * @param desc the symbolic descriptor for the method type */ @@ -115,25 +167,24 @@ default Utf8Entry utf8Entry(MethodTypeDesc desc) { } /** - * {@return A {@link ClassEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the binary name of a class or interface or the field descriptor + * string of an array type. * - * @param ne the constant pool entry describing the internal name of the class + * @param ne the {@code Utf8Entry} + * @see ClassEntry#name() ClassEntry::name */ ClassEntry classEntry(Utf8Entry ne); /** - * {@return A {@link ClassEntry} describing the class described by - * provided {@linkplain ClassDesc}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} describing the same reference type + * as the provided {@link ClassDesc}} * - * @param classDesc the symbolic descriptor for the class - * @throws IllegalArgumentException if {@code classDesc} represents a primitive type + * @param classDesc the symbolic descriptor for the reference type + * @throws IllegalArgumentException if {@code classDesc} represents a + * primitive type + * @see ClassEntry#asSymbol() ClassEntry::asSymbol */ default ClassEntry classEntry(ClassDesc classDesc) { if (requireNonNull(classDesc).isPrimitive()) { @@ -145,196 +196,191 @@ default ClassEntry classEntry(ClassDesc classDesc) { } /** - * {@return A {@link PackageEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the name of a package. * - * @param nameEntry the constant pool entry describing the internal name of - * the package + * @param nameEntry the {@code Utf8Entry} + * @see PackageEntry#name() PackageEntry::name */ PackageEntry packageEntry(Utf8Entry nameEntry); /** - * {@return A {@link PackageEntry} describing the class described by - * provided {@linkplain PackageDesc}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} describing the same package as the + * provided {@link PackageDesc}} * - * @param packageDesc the symbolic descriptor for the class + * @param packageDesc the symbolic descriptor for the package + * @see PackageEntry#asSymbol() PackageEntry::asSymbol */ default PackageEntry packageEntry(PackageDesc packageDesc) { return packageEntry(utf8Entry(packageDesc.internalName())); } /** - * {@return A {@link ModuleEntry} describing the module whose name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the module name. * * @param moduleName the constant pool entry describing the module name + * @see ModuleEntry#name() ModuleEntry::name */ ModuleEntry moduleEntry(Utf8Entry moduleName); /** - * {@return A {@link ModuleEntry} describing the module described by - * provided {@linkplain ModuleDesc}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} describing the same module as the provided + * {@link ModuleDesc}} * - * @param moduleDesc the symbolic descriptor for the class + * @param moduleDesc the symbolic descriptor for the module + * @see ModuleEntry#asSymbol() ModuleEntry::asSymbol */ default ModuleEntry moduleEntry(ModuleDesc moduleDesc) { return moduleEntry(utf8Entry(moduleDesc.name())); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} referring to the provided name and + * type {@link Utf8Entry}} The name {@code Utf8Entry} describes an + * unqualified name or the special name {@value ConstantDescs#INIT_NAME}, + * and the type {@code Utf8Entry} describes a field or method descriptor + * string. * - * @param nameEntry the member name - * @param typeEntry the member field or method descriptor + * @param nameEntry the name {@code Utf8Entry} + * @param typeEntry the type {@code Utf8Entry} + * @see NameAndTypeEntry#name() NameAndTypeEntry::name + * @see NameAndTypeEntry#type() NameAndTypeEntry::type */ NameAndTypeEntry nameAndTypeEntry(Utf8Entry nameEntry, Utf8Entry typeEntry); /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided unqualified + * name and field descriptor} * - * @param name the member name - * @param type the symbolic descriptor for a field type + * @param name the unqualified name + * @param type the field descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, ClassDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided name and + * method descriptor} The name can be an unqualified name or the + * special name {@value ConstantDescs#INIT_NAME}. * - * @param name the member name - * @param type the symbolic descriptor for a method type + * @param name the unqualified name, or {@value ConstantDescs#INIT_NAME} + * @param type the method descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, MethodTypeDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class or + * interface that has this field as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the field descriptor + * for this field. * - * @param owner the class the field is a member of - * @param nameAndType the name and type of the field + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see FieldRefEntry#owner() FieldRefEntry::owner + * @see FieldRefEntry#nameAndType() FieldRefEntry::nameAndType */ FieldRefEntry fieldRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} describing a field of a class} * - * @param owner the class the field is a member of - * @param name the name of the field - * @param type the type of the field + * @param owner the class or interface the field is a member of + * @param name the unqualified name of the field + * @param type the field descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see FieldRefEntry#typeSymbol() FieldRefEntry::typeSymbol */ default FieldRefEntry fieldRefEntry(ClassDesc owner, String name, ClassDesc type) { return fieldRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class that + * has this method as a member, and the {@code NameAndTypeEntry} describes + * the unqualified name or the special name {@value ConstantDescs#INIT_NAME} + * and the method descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see MethodRefEntry#owner() MethodRefEntry::owner + * @see MethodRefEntry#nameAndType() MethodRefEntry::nameAndType */ MethodRefEntry methodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} describing a method of a class} * * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param name the unqualified name, or special name {@value + * ConstantDescs#INIT_NAME}, of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see MethodRefEntry#typeSymbol() MethodRefEntry::typeSymbol */ default MethodRefEntry methodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return methodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} referring to a {@link + * ClassEntry} and a {@link NameAndTypeEntry}} The {@code ClassEntry} + * describes an interface that has this method as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the method + * descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InterfaceMethodRefEntry#owner() InterfaceMethodRefEntry::owner + * @see InterfaceMethodRefEntry#nameAndType() + * InterfaceMethodRefEntry::nameAndType */ InterfaceMethodRefEntry interfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} describing a method of an + * interface} * - * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param owner the interface the method is a member of + * @param name the unqualified name of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see InterfaceMethodRefEntry#typeSymbol() InterfaceMethodRefEntry::typeSymbol */ default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return interfaceMethodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} describing the same method type as + * the provided {@link MethodTypeDesc}} * * @param descriptor the symbolic descriptor of the method type + * @see MethodTypeEntry#asSymbol() MethodTypeEntry::asSymbol */ MethodTypeEntry methodTypeEntry(MethodTypeDesc descriptor); /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} represents a method descriptor string. * - * @param descriptor the constant pool entry for the method type descriptor + * @param descriptor the {@code Utf8Entry} + * @see MethodTypeEntry#descriptor() MethodTypeEntry::descriptor */ MethodTypeEntry methodTypeEntry(Utf8Entry descriptor); /** - * {@return A {@link MethodHandleEntry} describing a direct method handle} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} describing the same method handle as + * the given {@link DirectMethodHandleDesc}} * * @param descriptor the symbolic descriptor of the method handle + * @see MethodHandleEntry#asSymbol() MethodHandleEntry::asSymbol */ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { var owner = classEntry(descriptor.owner()); @@ -347,125 +393,133 @@ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { } /** - * {@return A {@link MethodHandleEntry} describing a field accessor or method} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} encoding a reference kind and + * referring to a {@link MemberRefEntry}} The reference kind must be + * in {@code [1, 9]}, and the {@code MemberRefEntry} is subject to + * various restrictions based on the reference kind (JVMS {@jvms 4.4.8}). * - * @param refKind the reference kind of the method handle (JVMS {@jvms 4.4.8}) - * @param reference the constant pool entry describing the field or method + * @param refKind the reference kind of the method handle + * @param reference the {@code MemberRefEntry} + * @see MethodHandleInfo##refkinds Reference kinds + * @see MethodHandleEntry#kind() MethodHandleEntry::kind + * @see MethodHandleEntry#reference() MethodHandleEntry::reference */ MethodHandleEntry methodHandleEntry(int refKind, MemberRefEntry reference); /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} describing the same dynamic call + * site as the provided {@link DynamicCallSiteDesc}} * - * @param dcsd the symbolic descriptor of the method handle + * @param dcsd the symbolic descriptor of the dynamic call site + * @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol */ default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) { return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType())); } /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a method descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InvokeDynamicEntry#bootstrap() InvokeDynamicEntry::bootstrap + * @see InvokeDynamicEntry#nameAndType() InvokeDynamicEntry::nameAndType */ InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} describing the dynamic constant + * as the provided {@link DynamicConstantDesc}} * * @param dcd the symbolic descriptor of the constant + * @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol */ default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc dcd) { return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType())); } /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a field descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see ConstantDynamicEntry#bootstrap() ConstantDynamicEntry::bootstrap + * @see ConstantDynamicEntry#nameAndType() ConstantDynamicEntry::nameAndType */ ConstantDynamicEntry constantDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return An {@link IntegerEntry} describing the provided value} - * If an integer entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return an {@link IntegerEntry} describing the provided value} * * @param value the value + * @see IntegerEntry#intValue() IntegerEntry::intValue */ IntegerEntry intEntry(int value); /** - * {@return A {@link FloatEntry} describing the provided value} - * If a float entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link FloatEntry} describing the provided value} * * @param value the value + * @see FloatEntry#floatValue() FloatEntry::floatValue */ FloatEntry floatEntry(float value); /** - * {@return A {@link LongEntry} describing the provided value} - * If a long entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link LongEntry} describing the provided value} * * @param value the value + * @see LongEntry#longValue() LongEntry::longValue */ LongEntry longEntry(long value); /** - * {@return A {@link DoubleEntry} describing the provided value} - * If a double entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link DoubleEntry} describing the provided value} * * @param value the value + * @see DoubleEntry#doubleValue() DoubleEntry::doubleValue */ DoubleEntry doubleEntry(double value); /** - * {@return A {@link StringEntry} referencing the provided UTF8 entry} - * If a String entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} describes the string value. * - * @param utf8 the UTF8 entry describing the string + * @param utf8 the {@code Utf8Entry} + * @see StringEntry#utf8() StringEntry::utf8 */ StringEntry stringEntry(Utf8Entry utf8); /** - * {@return A {@link StringEntry} describing the provided value} - * If a string entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} describing the provided value} * * @param value the value + * @see StringEntry#stringValue() StringEntry::stringValue */ default StringEntry stringEntry(String value) { return stringEntry(utf8Entry(value)); } /** - * {@return A {@link ConstantValueEntry} describing the provided - * Integer, Long, Float, Double, or String constant} + * {@return a {@link ConstantValueEntry} describing the provided constant + * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link + * String} value} * - * @param c the constant - * @see ConstantValueEntry#constantValue() + * @param c the provided constant value + * @throws IllegalArgumentException if the value is not one of {@code + * Integer}, {@code Long}, {@code Float}, {@code Double}, or {@code + * String} + * @see ConstantValueEntry#constantValue() ConstantValueEntry::constantValue + * @see ConstantValueAttribute#of(ConstantDesc) + * ConstantValueAttribute::of(ConstantDesc) */ default ConstantValueEntry constantValueEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -477,13 +531,10 @@ default ConstantValueEntry constantValueEntry(ConstantDesc c) { } /** - * {@return A {@link LoadableConstantEntry} describing the provided - * constant} The constant should be an Integer, String, Long, Float, - * Double, ClassDesc (for a Class constant), MethodTypeDesc (for a MethodType - * constant), DirectMethodHandleDesc (for a MethodHandle constant), or - * a DynamicConstantDesc (for a dynamic constant.) + * {@return a {@link LoadableConstantEntry} describing the provided constant + * value} * - * @param c the constant + * @param c the nominal descriptor for the constant */ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -500,10 +551,10 @@ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { /** * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * bootstrap method and arguments} * * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param arguments the arguments */ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, List arguments) { @@ -512,11 +563,16 @@ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, } /** - * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * {@return a {@link BootstrapMethodEntry} referring to a {@link + * MethodHandleEntry} and a list of {@link LoadableConstantEntry}} + * The {@code MethodHandleEntry} is the bootstrap method, and the + * list of {@code LoadableConstantEntry} is the arguments. * - * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param methodReference the {@code MethodHandleEntry} + * @param arguments the list of {@code LoadableConstantEntry} + * @see BootstrapMethodEntry#bootstrapMethod() + * BootstrapMethodEntry::bootstrapMethod + * @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments */ BootstrapMethodEntry bsmEntry(MethodHandleEntry methodReference, List arguments); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java index ce5ed26c4c9..bb3b33ba21c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -27,7 +27,9 @@ /** * Thrown to indicate that requested entry cannot be obtained from the constant - * pool. + * pool or the bootstrap method table. This is also thrown when the lazy + * evaluation of constant pool or bootstrap method table entries encounter + * format errors. * * @since 24 */ @@ -47,7 +49,8 @@ public ConstantPoolException() { * Constructs a {@code ConstantPoolException} with the specified detail * message. * - * @param message the detail message. + * @param message the detail message, may be {@code null} for no detail + * message */ public ConstantPoolException(String message) { super(message); @@ -55,11 +58,10 @@ public ConstantPoolException(String message) { /** * Constructs a {@code ConstantPoolException} with the specified cause and - * a detail message of {@code (cause==null ? null : cause.toString())}. - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) + * a detail message of {@code cause == null ? null : cause.toString()}. + * + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(Throwable cause) { super(cause); @@ -69,12 +71,10 @@ public ConstantPoolException(Throwable cause) { * Constructs a {@code ConstantPoolException} with the specified detail * message and cause. * - * @param message the detail message (which is saved for later retrieval - * by the {@link Throwable#getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value - * is permitted, and indicates that the cause is nonexistent or - * unknown.) + * @param message the detail message, may be {@code null} for no detail + * message + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(String message, Throwable cause) { super(message, cause); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java index ae746042aa4..8613fdd2cb9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -28,10 +28,11 @@ import java.lang.constant.ConstantDesc; /** - * Models a constant pool entry that can be used as the constant in a - * {@link Attributes#constantValue() ConstantValue} attribute; this includes the four - * primitive constant types and {@linkplain String} constants. + * Marker interface for constant pool entries that can represent constant values + * in the {@link Attributes#constantValue() ConstantValue} attribute. * + * @see ConstantPoolBuilder#constantValueEntry + * ConstantPoolBuilder::constantValueEntry * @sealedGraph * @since 24 */ @@ -39,8 +40,8 @@ public sealed interface ConstantValueEntry extends LoadableConstantEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, StringEntry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double}, or {@link String}. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link String}. * * @see ConstantPoolBuilder#constantValueEntry(ConstantDesc) */ diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java index ebc3a837bb0..bc6956b5bf5 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,10 +29,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Double_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Double_info} structure, representing a {@code + * double} constant, in the constant pool of a {@code class} file. + *

    + * The use of a {@code DoubleEntry} is modeled by a {@code double}. Conversions + * are through {@link ConstantPoolBuilder#doubleEntry} and {@link #doubleValue()}. + * In the conversions, all NaN values of the {@code double} may be collapsed + * into a single {@linkplain Double#NaN "canonical" NaN value}. + *

    + * A double entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#doubleEntry ConstantPoolBuilder::doubleEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface DoubleEntry @@ -40,13 +50,13 @@ public sealed interface DoubleEntry permits AbstractPoolEntry.DoubleEntryImpl { /** - * {@return the double value} + * {@return the {@code double} value} + * + * @see ConstantPoolBuilder#doubleEntry(double) + * ConstantPoolBuilder::doubleEntry(double) */ double doubleValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.DOUBLE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java index 3ec4fbbdbee..b72424db44e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -27,10 +27,27 @@ import java.lang.classfile.BootstrapMethodEntry; /** - * Models a dynamic constant pool entry, which is either {@link ConstantDynamicEntry} - * or {@link InvokeDynamicEntry}. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Superinterface modeling dynamically-computed constant pool entries, which + * include {@link ConstantDynamicEntry} and {@link InvokeDynamicEntry}, in the + * constant pool of a {@code class} file. + *

    + * Different types of dynamically-computed constant pool entries bear structural + * similarities, but they appear in distinct locations. As a result, their uses + * are represented by different symbolic descriptors, specific to each subtype. + *

    + * A dynamic constant entry is composite: + * {@snippet lang=text : + * DynamicConstantPoolEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @see java.lang.invoke##jvm_mods Dynamic resolution of call sites and + * constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures + * @jvms 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution * @sealedGraph * @since 24 */ @@ -39,28 +56,50 @@ public sealed interface DynamicConstantPoolEntry extends PoolEntry /** * {@return the entry in the bootstrap method table for this constant} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ BootstrapMethodEntry bootstrap(); /** - * {@return index of the entry in the bootstrap method table for this constant} + * {@return index of the entry in the bootstrap method table for this + * constant} The return value is equivalent to {@code + * bootstrap().bsmIndex()}. */ int bootstrapMethodIndex(); /** - * {@return the invocation name and type} + * {@return the name and the descriptor string indicated by this symbolic + * reference} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ NameAndTypeEntry nameAndType(); /** - * {@return the invocation name} + * {@return the name indicated by this symbolic reference} */ default Utf8Entry name() { return nameAndType().name(); } /** - * {@return the invocation type} + * {@return the descriptor string indicated by this symbolic reference} + * This is a field descriptor string if this entry is a {@link + * ConstantDynamicEntry}, or a method descriptor string if this entry is a + * {@link InvokeDynamicEntry}. + * + * @apiNote + * Each subinterface has its specific accessor named {@code typeSymbol} for + * the symbolic descriptor derived from this descriptor string. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java index 47f5b6710d8..9f984acd7ba 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_Fieldref_info} structure, or a symbolic reference + * to a field, in the constant pool of a {@code class} file. + *

    + * A field reference constant pool entry is composite: + * {@snippet lang=text : + * // @link substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassEntry, NameAndTypeEntry)" : + * FieldRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() nameAndType.type()} represents a {@linkplain + * #typeSymbol() field descriptor} string. * + * @see ConstantPoolBuilder#fieldRefEntry ConstantPoolBuilder::fieldRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface FieldRefEntry extends MemberRefEntry permits AbstractPoolEntry.FieldRefEntryImpl { /** - * {@return a symbolic descriptor for the field's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type}} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java index eeb44e92b7c..2ccf3fb94e4 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,10 +29,17 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Float_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Float_info} structure, or a {@code float} constant, + * in the constant pool of a {@code class} file. + *

    + * The use of a {@code FloatEntry} is modeled by a {@code float}. Conversions + * are through {@link ConstantPoolBuilder#floatEntry} and {@link #floatValue()}. + * In the conversions, all NaN values of the {@code float} may be collapsed into + * a single {@linkplain Float#NaN "canonical" NaN value}. * + * @see ConstantPoolBuilder#floatEntry ConstantPoolBuilder::floatEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface FloatEntry @@ -40,14 +47,12 @@ public sealed interface FloatEntry permits AbstractPoolEntry.FloatEntryImpl { /** - * {@return the float value} + * {@return the {@code float} value} + * + * @see ConstantPoolBuilder#floatEntry(float) */ - float floatValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.FLOAT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java index 908f17d1cb7..d6d2c28ed57 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,10 +29,15 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Integer_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Integer_info} structure, or an {@code int} constant, + * in the constant pool of a {@code class} file. + *

    + * The use of a {@code IntegerEntry} is modeled by an {@code int}. Conversions + * are through {@link ConstantPoolBuilder#intEntry(int)} and {@link #intValue()}. * + * @see ConstantPoolBuilder#intEntry ConstantPoolBuilder::intEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface IntegerEntry @@ -40,13 +45,12 @@ public sealed interface IntegerEntry permits AbstractPoolEntry.IntegerEntryImpl { /** - * {@return the integer value} + * {@return the {@code int} value} + * + * @see ConstantPoolBuilder#intEntry(int) */ int intValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.INT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java index 7b1a94f123a..e29c9f5b6f9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,10 +30,26 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_InterfaceMethodRef_info} structure, or a symbolic + * reference to an interface method, in the constant pool of a {@code class} + * file. + *

    + * An interface method reference entry is composite: + * {@snippet lang=text : + * // @link substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassEntry, NameAndTypeEntry)" : + * InterfaceMethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @see ConstantPoolBuilder#interfaceMethodRefEntry + * ConstantPoolBuilder::interfaceMethodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface InterfaceMethodRefEntry @@ -41,7 +57,7 @@ public sealed interface InterfaceMethodRefEntry permits AbstractPoolEntry.InterfaceMethodRefEntryImpl { /** - * {@return a symbolic descriptor for the interface method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java index 0cc8b6823df..02c2fce2e02 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -32,9 +32,38 @@ import jdk.internal.classfile.impl.Util; /** - * Models a constant pool entry for a dynamic call site. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_InvokeDynamic_info} structure, or the symbolic + * reference to a {@index "dynamically-computed call site"}, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code InvokeDynamicEntry} is modeled by a {@link + * DynamicCallSiteDesc} symbolic descriptor. It can be obtained from {@link + * #asSymbol() InvokeDynamicEntry::asSymbol} and converted back to a constant + * pool entry through {@link ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry}. + *

    + * An invoke dynamic entry is composite: + * {@snippet lang=text : + * // @link substring="InvokeDynamicEntry" target="ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * InvokeDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @apiNote + * A dynamically-computed call site is frequently called a {@index "dynamic + * call site"}, or an {@index "indy"}, from the abbreviation of + * "invoke dynamic". + * + * @see ConstantPoolBuilder#invokeDynamicEntry + * ConstantPoolBuilder::invokeDynamicEntry + * @see DynamicCallSiteDesc + * @see java.lang.invoke##indyinsn Dynamically-computed call sites + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface InvokeDynamicEntry @@ -42,14 +71,18 @@ public sealed interface InvokeDynamicEntry permits AbstractPoolEntry.InvokeDynamicEntryImpl { /** - * {@return a symbolic descriptor for the call site's invocation type} + * {@return a symbolic descriptor for the {@linkplain #type() invocation + * type} of this dynamic call site} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); } /** - * {@return a symbolic descriptor for the dynamic call site} + * {@return a symbolic descriptor for this dynamic call site} + * + * @see ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry(DynamicCallSiteDesc) */ default DynamicCallSiteDesc asSymbol() { return DynamicCallSiteDesc.of(bootstrap().bootstrapMethod().asSymbol(), diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java index 32f85f64c7e..9137bebea35 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,13 +24,22 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.ConstantDesc; /** * Marker interface for constant pool entries suitable for loading via the - * {@code LDC} instructions. + * {@link ConstantInstruction.LoadConstantInstruction ldc} instructions. + *

    + * The use of a {@code LoadableConstantEntry} is modeled by a {@link ConstantDesc}. + * Conversions are through {@link ConstantPoolBuilder#loadableConstantEntry(ConstantDesc)} + * and {@link #constantValue()}. * + * @see CodeBuilder#ldc(LoadableConstantEntry) + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -38,12 +47,19 @@ public sealed interface LoadableConstantEntry extends PoolEntry permits ClassEntry, ConstantDynamicEntry, ConstantValueEntry, MethodHandleEntry, MethodTypeEntry { /** - * {@return the constant described by this entry} + * {@return a symbolic descriptor of this constant} + * + * @see ConstantPoolBuilder#loadableConstantEntry(ConstantDesc) */ ConstantDesc constantValue(); /** - * {@return the type of the constant} + * {@return the data type of this constant} + *

    + * If the data type is of {@linkplain TypeKind#slotSize() category} 2, this + * constant must be loaded with {@link Opcode#LDC2_W ldc2_w}; otherwise, the + * data type is of category 1, and this constant must be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC_W ldc_w}. */ default TypeKind typeKind() { return TypeKind.REFERENCE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java index cd38dcfe014..dbf947d1f1d 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,10 +29,18 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Long_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Long_info} structure, or a {@code long} constant, in + * the constant pool of a {@code class} file. + *

    + * The use of a {@code LongEntry} is modeled by a {@code long}. Conversions are + * through {@link ConstantPoolBuilder#longEntry(long)} and {@link #longValue()}. + *

    + * A long entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#longEntry ConstantPoolBuilder::longEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface LongEntry @@ -40,7 +48,10 @@ public sealed interface LongEntry permits AbstractPoolEntry.LongEntryImpl { /** - * {@return the long value} + * {@return the {@code long} value} + * + * @see ConstantPoolBuilder#longEntry(long) + * ConstantPoolBuilder::longEntry(long) */ long longValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java index 12d68796dd7..3d59a3c96c9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,24 +24,45 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Opcode; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a member reference constant in the constant pool of a classfile, - * which includes references to fields, methods, and interface methods. + * Superinterface modeling symbolic references to a member of a class or interface + * in the constant pool of a {@code class} file, which include references to + * {@linkplain FieldRefEntry fields}, {@linkplain MethodRefEntry class methods}, + * and {@linkplain InterfaceMethodRefEntry interface methods}. + *

    + * Different types of symbolic references to a member of a class or interface + * bear structural similarities and share parts of the resolution processes, and + * they can sometimes appear in the same locations. For example, both {@link + * MethodRefEntry} and {@link InterfaceMethodRefEntry} can appear in an {@link + * Opcode#INVOKESTATIC invokestatic} instruction. + *

    + * A member reference entry is composite: + * {@snippet lang=text : + * MemberRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @sealedGraph * @since 24 */ public sealed interface MemberRefEntry extends PoolEntry permits FieldRefEntry, InterfaceMethodRefEntry, MethodRefEntry, AbstractPoolEntry.AbstractMemberRefEntry { /** - * {@return the class in which this member ref lives} + * {@return the class or interface which this member belongs to} */ ClassEntry owner(); /** - * {@return the name and type of the member} + * {@return the name and descriptor string of the member} */ NameAndTypeEntry nameAndType(); @@ -53,7 +74,14 @@ default Utf8Entry name() { } /** - * {@return the type of the member} + * {@return the descriptor string of the member} This is a field descriptor + * string if this entry is a {@link FieldRefEntry}, or a method descriptor + * string if this entry is a {@link MethodRefEntry} or {@link + * InterfaceMethodRefEntry}. + * + * @apiNote + * Each subinterface defines a {@code typeSymbol()} accessor for the + * symbolic descriptor for the member type. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java index d2e08ef178c..22c07236e8a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -26,13 +26,35 @@ import java.lang.constant.ConstantDesc; import java.lang.constant.DirectMethodHandleDesc; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleInfo; import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure + * Models a {@code CONSTANT_MethodHandle_info} structure, or a symbolic + * reference to a {@linkplain MethodHandle method handle}, in the constant pool + * of a {@code class} file. The method handle directly accesses an accessible + * method, field, or constructor. + *

    + * The use of a {@code MethodHandleEntry} is modeled by a {@link + * DirectMethodHandleDesc}. Conversions are through {@link + * ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)} and {@link + * #asSymbol()}. + *

    + * A method handle entry is composite: + * {@snippet lang=text : + * // @link substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(int, MemberRefEntry)" : + * MethodHandleEntry( + * int refKind, // @link substring="refKind" target="#kind()" + * MemberRefEntry reference // @link substring="reference" target="#reference()" + * ) + * } + * where {@code refKind} is in the range {@code [1, 9]}. + * + * @see ConstantPoolBuilder#methodHandleEntry + * ConstantPoolBuilder::methodHandleEntry + * @jvms 4.4.8 The {@code CONSTANT_MethodHandle_info} Structure * * @since 24 */ @@ -40,6 +62,11 @@ public sealed interface MethodHandleEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodHandleEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); @@ -47,17 +74,22 @@ default ConstantDesc constantValue() { /** * {@return the reference kind of this method handle (JVMS {@jvms 4.4.8})} - * @see java.lang.invoke.MethodHandleInfo + * + * @see MethodHandleInfo##refkinds Reference kinds */ int kind(); /** - * {@return the constant pool entry describing the method} + * {@return the constant pool entry describing the field or method, + * according to the {@linkplain #kind() reference kind}} */ MemberRefEntry reference(); /** * {@return a symbolic descriptor for this method handle} + * + * @see ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc) + * ConstantPoolBuilder::methodHandleEntry(DirectMethodHandleDesc) */ DirectMethodHandleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java index 5be9e88fa2f..29503741ec3 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_MethodRef_info} structure, or a symbolic reference + * to a class method, in the constant pool of a {@code class} file. + *

    + * A class method reference entry is composite: + * {@snippet lang=text : + * // @link substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassEntry, NameAndTypeEntry)" : + * MethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the type in the {@code NameAndTypeEntry} is a {@linkplain #typeSymbol() + * method descriptor} string. * + * @see ConstantPoolBuilder#methodRefEntry ConstantPoolBuilder::methodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface MethodRefEntry extends MemberRefEntry permits AbstractPoolEntry.MethodRefEntryImpl { /** - * {@return a symbolic descriptor for the method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java index b6fad856358..5da36502678 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -30,28 +30,46 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.9 The CONSTANT_MethodType_info Structure + * Models a {@code CONSTANT_MethodType_info} structure, or a symbolic reference + * to a method type, in the constant pool of a {@code class} file. + *

    + * The use of a {@code MethodTypeEntry} is modeled by a {@link MethodTypeDesc}. + * Conversions are through {@link ConstantPoolBuilder#methodTypeEntry(MethodTypeDesc)} + * and {@link #asSymbol()}. + *

    + * A method type entry is composite: + * {@snippet lang=text : + * // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(Utf8Entry)" : + * MethodTypeEntry(Utf8Entry descriptor) // @link substring="descriptor" target="#descriptor()" + * } + * where {@code descriptor} is a {@linkplain #asSymbol() method descriptor} + * string. * + * @jvms 4.4.9 The {@code CONSTANT_MethodType_info} Structure * @since 24 */ public sealed interface MethodTypeEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodTypeEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the constant pool entry describing the method type} + * {@return the {@linkplain #asSymbol() method descriptor} string} */ Utf8Entry descriptor(); /** - * {@return a symbolic descriptor for the method type} + * {@return a symbolic descriptor for the {@linkplain #descriptor() method + * type}} */ MethodTypeDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java index d0cdae5678f..fd920aa1231 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,21 +29,32 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Module_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.11 The CONSTANT_Module_info Structure + * Models a {@code CONSTANT_Module_info} structure, denoting a module, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code ModuleEntry} is modeled by a {@link ModuleDesc}. + * Conversions are through {@link ConstantPoolBuilder#moduleEntry(ModuleDesc)} + * and {@link #asSymbol()}. + *

    + * A module entry is composite: + * {@snippet lang=text : + * // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(Utf8Entry)" : + * ModuleEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is a {@linkplain #asSymbol() module name}. * + * @jvms 4.4.11 The {@code CONSTANT_Module_info} Structure * @since 24 */ public sealed interface ModuleEntry extends PoolEntry permits AbstractPoolEntry.ModuleEntryImpl { /** - * {@return the name of the module} + * {@return the name of the {@linkplain #asSymbol() module}} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the module} + * {@return a symbolic descriptor for the {@linkplain #name() module name}} */ ModuleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java index eff7e3456d1..38a23b0940e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,13 +24,36 @@ */ package java.lang.classfile.constantpool; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure + * Models a {@code CONSTANT_NameAndType_info} structure, representing a field or + * method, in the constant pool of a {@code class} file. + *

    + * The use of a {@code NameAndTypeEntry} is symbolically represented as a + * {@code String name}, and a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * ClassDesc) ClassDesc} or a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * MethodTypeDesc) MethodTypeDesc} {@code type}, depending on where this {@code + * NameAndTypeEntry} appears. The accessors to the symbolic descriptors for the + * {@code type} is defined on a per-use-site basis, such as {@link + * FieldRefEntry#typeSymbol()} returning a {@code ClassDesc}, and {@link + * MethodRefEntry#typeSymbol()} returning a {@code MethodTypeDesc}. + *

    + * A name and type entry is composite: + * {@snippet lang=text : + * NameAndTypeEntry( // @link substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(Utf8Entry, Utf8Entry)" + * Utf8Entry name, // @link substring="name" target="#name()" + * Utf8Entry type // @link substring="type" target="#type()" + * ) + * } + * where {@code name} is an unqualified name, and {@code type} is a field or + * method descriptor string. * + * @jvms 4.4.6 The {@code CONSTANT_NameAndType_info} Structure * @since 24 */ public sealed interface NameAndTypeEntry extends PoolEntry @@ -42,7 +65,10 @@ public sealed interface NameAndTypeEntry extends PoolEntry Utf8Entry name(); /** - * {@return the field or method descriptor} + * {@return the field or method {@linkplain TypeDescriptor descriptor} + * string} It is a method descriptor strings if it starts with {@code (}. + * Otherwise, it is a field descriptor string, and must start with one of + * the {@code BCDFIJSZL[} characters. */ Utf8Entry type(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java index 54ea2fc38e5..ec56d0a4870 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,21 +29,35 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Package_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.12 The CONSTANT_Package_info Structure + * Models a {@code CONSTANT_Package_info}, representing a package, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code PackageEntry} is represented by a {@link PackageDesc} + * that does not represent the unnamed package. Conversions are through + * {@link ConstantPoolBuilder#packageEntry(PackageDesc)} and + * {@link #asSymbol()}. + *

    + * A package entry is composite: + * {@snippet lang=text : + * // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(Utf8Entry)" : + * PackageEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is the {@linkplain ClassEntry##internalname internal form} + * of a binary package name and is not empty. * + * @jvms 4.4.12 The {@code CONSTANT_Package_info} Structure * @since 24 */ public sealed interface PackageEntry extends PoolEntry permits AbstractPoolEntry.PackageEntryImpl { /** - * {@return the package name} + * {@return the {@linkplain ClassEntry##internalname internal form} of the + * {@linkplain #asSymbol() package} name} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the package name} + * {@return a symbolic descriptor for the {@linkplain #name() package name}} */ PackageDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java index 5762a92a061..5d27e54e679 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,9 +24,28 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Attribute; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.Opcode; +import java.lang.classfile.TypeKind; + /** - * Models an entry in the constant pool of a classfile. + * Models an entry in the constant pool of a {@code class} file. Entries are + * read from {@code class} files, and can be created with a {@link + * ConstantPoolBuilder} to write to {@code class} files. + * + * @implNote + *

    Unbound Constant Pool Entries

    + * Implementations may create unbound constant pool entries not belonging to + * an actual constant pool. They conveniently represent constant pool entries + * referred by unbound {@linkplain Attribute attributes} not read from a {@code + * class} file. Their {@link #index() index()} return a non-positive invalid + * value, and behaviors of their {@link #constantPool() constantPool()} are + * unspecified. They are considered alien to any {@linkplain + * ClassFileBuilder#constantPool() contextual constant pool} and will be + * converted when they are written to {@code class} files. * + * @see ConstantPoolBuilder##alien Alien Constant Pool Entries * @sealedGraph * @since 24 */ @@ -88,6 +107,14 @@ public sealed interface PoolEntry /** * {@return the constant pool this entry is from} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * PoolEntry entry}, use {@link ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry belongs to the builder. + * + * @see ##unbound Unbound Constant Pool Entries */ ConstantPool constantPool(); @@ -102,11 +129,32 @@ public sealed interface PoolEntry /** * {@return the index within the constant pool corresponding to this entry} + * A valid index is always positive; if the index is non-positive, this + * entry is {@linkplain ##unbound unbound}. + * + * @see ##unbound Unbound Constant Pool Entries */ int index(); /** * {@return the number of constant pool slots this entry consumes} + *

    + * All pool entries except {@link LongEntry CONSTANT_Long} and {@link + * DoubleEntry CONSTANT_Double} have width {@code 1}. These two exceptions + * have width {@code 2}, and their subsequent indices at {@link #index() + * index() + 1} are considered unusable. + * + * @apiNote + * If this entry is {@linkplain LoadableConstantEntry loadable}, the width + * of this entry does not decide if this entry should be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC2_W ldc2_w}. For example, {@link + * ConstantDynamicEntry} always has width {@code 1}, but it must be loaded + * with {@code ldc2_w} if its {@linkplain ConstantDynamicEntry#typeKind() + * type} is {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double}. + * Use {@link LoadableConstantEntry#typeKind() typeKind().slotSize()} to + * determine the loading instruction instead. + * + * @see ConstantPool##index Index in the Constant Pool */ int width(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java index 03ff7652f67..8a0bbb4b015 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -27,10 +27,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_String_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.3 The CONSTANT_String_info Structure + * Models a {@code CONSTANT_String_info} structure, or a string constant, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code StringEntry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#stringEntry(String)} and + * {@link #stringValue()}. + *

    + * A string entry is composite: + * {@snippet lang=text : + * // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(Utf8Entry)" : + * StringEntry(Utf8Entry utf8) // @link substring="utf8" target="#utf8()" + * } * + * @jvms 4.4.3 The {@code CONSTANT_String_info} Structure * @since 24 */ public sealed interface StringEntry @@ -38,11 +48,15 @@ public sealed interface StringEntry permits AbstractPoolEntry.StringEntryImpl { /** * {@return the UTF constant pool entry describing the string contents} + * + * @see ConstantPoolBuilder#stringEntry(Utf8Entry) */ Utf8Entry utf8(); /** * {@return the string value for this entry} + * + * @see ConstantPoolBuilder#stringEntry(String) */ String stringValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java index db03bf6a403..1d885051b2b 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,13 +24,40 @@ */ package java.lang.classfile.constantpool; +import java.io.DataInput; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.7 The CONSTANT_Utf8_info Structure + * Models a {@code CONSTANT_UTF8_info} constant, representing strings, in the + * constant pool of a {@code class} file. This describes strings in the + * {@linkplain DataInput##modified-utf-8 Modified UTF-8} format. + *

    + * The use of a {@code Utf8Entry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#utf8Entry(String)} and + * {@link #stringValue()}. + *

    + * Some uses of {@code Utf8Entry} represent field or method {@linkplain + * TypeDescriptor#descriptorString() descriptor strings}, symbolically + * represented as {@link ClassDesc} or {@link MethodTypeDesc}, depending on + * where a {@code Utf8Entry} appear. Entries representing such uses are created + * with {@link ConstantPoolBuilder#utf8Entry(ClassDesc)} and {@link + * ConstantPoolBuilder#utf8Entry(MethodTypeDesc)}, and they can be converted to + * symbolic descriptors on a per-use-site basis, such as in {@link + * AnnotationValue.OfClass#classSymbol()} and {@link MethodModel#methodTypeSymbol()}. + *

    + * Unlike most constant pool entries, a UTF-8 entry is of flexible length: it is + * represented as an array structure, with an {@code u2} for the data length in + * bytes, followed by that number of bytes of Modified UTF-8 data. It can + * represent at most 65535 bytes of data due to the physical restrictions. * + * @jvms 4.4.7 The {@code CONSTANT_Utf8_info} Structure + * @see DataInput##modified-utf-8 Modified UTF-8 * @since 24 */ public sealed interface Utf8Entry @@ -39,6 +66,15 @@ public sealed interface Utf8Entry /** * {@return the string value for this entry} + * + * @apiNote + * A {@code Utf8Entry} can be used directly as a {@link CharSequence} if + * {@code String} functionalities are not strictly desired. If only string + * equivalence is desired, {@link #equalsString(String) equalsString} should + * be used. Reduction of string processing can significantly improve {@code + * class} file reading performance. + * + * @see ConstantPoolBuilder#utf8Entry(String) */ String stringValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java index 83039c6565c..66e72496d3a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -24,11 +24,59 @@ */ /** - *

    Provides interfaces describing classfile constant pool entries for the {@link java.lang.classfile} library.

    + *

    Provides interfaces describing constant pool entries for the {@link java.lang.classfile} library.

    * - * The {@code java.lang.classfile.constantpool} package contains interfaces describing classfile constant pool entries. + * The {@code java.lang.classfile.constantpool} package contains interfaces describing constant pool entries in the + * {@code class} file format. Constant pool entries are low-level models to faithfully represent the exact structure + * of a {@code class} file. + *

    + * Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an + * argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException} + * to be thrown. * + *

    Reading the constant pool entries

    + * When read from {@code class} files, the pool entries are lazily inflated; the contents of these entries, besides the + * bare structure, are not evaluated to speed up parsing. Entries to users interest, usually accessed from other models + * and elements, have their contents read on demand. For example, to search for methods, a user should filter first by + * access flags and then by method name, and use {@link Utf8Entry#equalsString(String)} instead of checking equality + * against {@link Utf8Entry#stringValue()}. This avoids inflation of UTF-8 entries as much as possible: + * {@snippet lang="java" class="PackageSnippets" region="isStaticWorkMethod"} + *

    + * The entries also define accessors to validated symbolic information with nominal descriptor abstractions from the + * {@link java.lang.constant} package. These symbolic information accessors perform validation against the read + * {@code class} files, and throw {@link IllegalArgumentException} when the accessed constant pool entry contains + * invalid data. The nominal descriptors represent validated data, which saves users from extra validations in future + * processing. + *

    + * Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed + * {@code class} file data can be thrown at any method invocation. For example, an exception may come from a {@link + * ClassEntry} when it is first read from the constant pool (referring to an invalid index or wrong type of entry), when + * its referred UTF-8 entry is expanded (malformed UTF-8 data), or when its symbolic information is accessed (the string + * is not valid for a class entry). + * + *

    Writing the constant pool entries

    + * In general, users do not need to worry about working with the constant pool and its entries when writing {@code + * class} files. Most Class-File API models and elements have two sets of factory methods: one that accepts symbolic + * information representing the uses, and another that accepts constant pool entries. The constant pool builder + * associated with {@code class} file builders, {@link ClassFileBuilder#constantPool}, automatically creates or reuses + * pool entries from the symbolic information. Validated data in symbolic information helps {@code class} file + * generation by avoiding extraneous parsing of raw constant pool entry data. + *

    + * As always, users can use factories that accept constant pool entries if they already have them by hand, or if they + * desire fine-grained control over {@code class} file generation. + *

    + * If many models and elements are reused from another {@link ClassModel} in class building, the class building process + * can use a constant pool builder that extends from the given {@code ClassModel}, available through {@link + * ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)}, so that byte data with constant pool + * references can be copied in batch, speeding up class building. This is especially applicable to class transformations, + * and {@link ClassFile.ConstantPoolSharingOption ConstantPoolSharingOption} exists to control this behavior. + * + * @jvms 4.4 The Constant Pool * @since 24 */ package java.lang.classfile.constantpool; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java new file mode 100644 index 00000000000..983aa1adb4c --- /dev/null +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java @@ -0,0 +1,43 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang.classfile.constantpool.snippet; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.MethodModel; +import java.lang.classfile.constantpool.Utf8Entry; + +class PackageSnippets { + + // @start region=isStaticWorkMethod + boolean isStaticWorkMethod(MethodModel method) { + // check static flag first to avoid unnecessary evaluation of UTF-8 entry + return (method.flags().flagsMask() & ClassFile.ACC_STATIC) != 0 + // use equalsString to avoid full conversion to String for comparison + // the Utf8Entry can also act as a basic CharSequence without full conversion + // @link substring="methodName" target="MethodModel#methodName" : + && method.methodName().equalsString("work"); // @link substring="equalsString" target="Utf8Entry#equalsString" + } + // @end +} diff --git a/src/java.base/share/classes/java/net/URLConnection.java b/src/java.base/share/classes/java/net/URLConnection.java index 69f71942561..585ab4fa15a 100644 --- a/src/java.base/share/classes/java/net/URLConnection.java +++ b/src/java.base/share/classes/java/net/URLConnection.java @@ -306,7 +306,7 @@ public static FileNameMap getFileNameMap() { if (map == null) { fileNameMap = map = new FileNameMap() { private final FileNameMap internalMap = - sun.net.www.MimeTable.loadTable(); + sun.net.www.MimeTable.getDefaultTable(); public String getContentTypeFor(String fileName) { return internalMap.getContentTypeFor(fileName); diff --git a/src/java.base/share/classes/java/nio/file/FileSystems.java b/src/java.base/share/classes/java/nio/file/FileSystems.java index ab0538a1d41..f60f798c6e2 100644 --- a/src/java.base/share/classes/java/nio/file/FileSystems.java +++ b/src/java.base/share/classes/java/nio/file/FileSystems.java @@ -34,6 +34,7 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; +import jdk.internal.loader.ClassLoaders; import jdk.internal.misc.VM; import sun.nio.fs.DefaultFileSystemProvider; @@ -112,11 +113,9 @@ private static FileSystemProvider getDefaultProvider() { if (propValue != null) { for (String cn: propValue.split(",")) { try { - Class c = Class - .forName(cn, true, ClassLoader.getSystemClassLoader()); - Constructor ctor = c - .getDeclaredConstructor(FileSystemProvider.class); - provider = (FileSystemProvider)ctor.newInstance(provider); + Class c = Class.forName(cn, true, ClassLoaders.appClassLoader()); + Constructor ctor = c.getDeclaredConstructor(FileSystemProvider.class); + provider = (FileSystemProvider) ctor.newInstance(provider); // must be "file" if (!provider.getScheme().equals("file")) @@ -146,13 +145,17 @@ private static FileSystemProvider getDefaultProvider() { * is invoked to create the default file system. * *

    If the system property {@code java.nio.file.spi.DefaultFileSystemProvider} - * is defined then it is taken to be a list of one or more fully-qualified - * names of concrete provider classes identified by the URI scheme - * {@code "file"}. Where the property is a list of more than one name then - * the names are separated by a comma. Each class is loaded, using the system - * class loader, and instantiated by invoking a one argument constructor - * whose formal parameter type is {@code FileSystemProvider}. The providers - * are loaded and instantiated in the order they are listed in the property. + * is defined then it is taken to be a list of one or more fully-qualified names + * of concrete provider classes identified by the URI scheme {@code "file"}. + * If the property is a list of more than one name then the names are separated + * by a comma character. Each provider class is a {@code public} class with a + * {@code public} constructor that has one formal parameter of type {@code + * FileSystemProvider}. If the provider class is in a named module then the module + * exports the package containing the provider class to at least {@code java.base}. + * Each provider class is loaded, using the + * {@linkplain ClassLoader#getSystemClassLoader() default system class loader}, + * and instantiated by invoking the constructor. The providers are loaded and + * instantiated in the order they are listed in the property. * If this process fails or a provider's scheme is not equal to {@code "file"} * then an unspecified error is thrown. URI schemes are normally compared * without regard to case but for the default provider, the scheme is diff --git a/src/java.base/share/classes/java/time/ZoneOffset.java b/src/java.base/share/classes/java/time/ZoneOffset.java index 14ac5fcfb6b..520a0e0b9a1 100644 --- a/src/java.base/share/classes/java/time/ZoneOffset.java +++ b/src/java.base/share/classes/java/time/ZoneOffset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -424,11 +424,17 @@ public static ZoneOffset ofTotalSeconds(int totalSeconds) { throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00"); } if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) { - return SECONDS_CACHE.computeIfAbsent(totalSeconds, totalSecs -> { - ZoneOffset result = new ZoneOffset(totalSecs); + Integer totalSecs = totalSeconds; + ZoneOffset result = SECONDS_CACHE.get(totalSecs); + if (result == null) { + result = new ZoneOffset(totalSeconds); + var existing = SECONDS_CACHE.putIfAbsent(totalSecs, result); + if (existing != null) { + result = existing; + } ID_CACHE.putIfAbsent(result.getId(), result); - return result; - }); + } + return result; } else { return new ZoneOffset(totalSeconds); } diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 33dea914b66..7c83de46c52 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1097,14 +1097,14 @@ public DateTimeFormatterBuilder appendLocalizedOffset(TextStyle style) { * During parsing, the text must match a known zone or offset. * There are two types of zone ID, offset-based, such as '+01:30' and * region-based, such as 'Europe/London'. These are parsed differently. - * If the parse starts with '+', '-', 'UT', 'UTC' or 'GMT', then the parser - * expects an offset-based zone and will not match region-based zones. - * The offset ID, such as '+02:30', may be at the start of the parse, - * or prefixed by 'UT', 'UTC' or 'GMT'. The offset ID parsing is - * equivalent to using {@link #appendOffset(String, String)} using the - * arguments 'HH:MM:ss' and the no offset string '0'. - * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser cannot - * match a following offset ID, then {@link ZoneOffset#UTC} is selected. + * If the parse starts with '+' or '-', then the parser expects an + * offset-based zone and will not match region-based zones. The offset + * ID parsing is equivalent to using {@link #appendOffset(String, String)} + * using the arguments 'HH:MM:ss' and the no offset string '0'. + * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser can + * match a following offset, then a region-based zone with the parsed + * offset will be returned, or else if the parser cannot match a following + * offset, then {@link ZoneOffset#UTC} is selected. * In all other cases, the list of known region-based zones is used to * find the longest available match. If no match is found, and the parse * starts with 'Z', then {@code ZoneOffset.UTC} is selected. @@ -1118,9 +1118,9 @@ public DateTimeFormatterBuilder appendLocalizedOffset(TextStyle style) { * "UTC" -- ZoneId.of("UTC") * "GMT" -- ZoneId.of("GMT") * "+01:30" -- ZoneOffset.of("+01:30") - * "UT+01:30" -- ZoneOffset.of("+01:30") - * "UTC+01:30" -- ZoneOffset.of("+01:30") - * "GMT+01:30" -- ZoneOffset.of("+01:30") + * "UT+01:30" -- ZoneId.of("UT+01:30") + * "UTC+01:30" -- ZoneId.of("UTC+01:30") + * "GMT+01:30" -- ZoneId.of("GMT+01:30") * * * @return this, for chaining, not null @@ -1135,8 +1135,7 @@ public DateTimeFormatterBuilder appendZoneId() { * Appends the time-zone region ID, such as 'Europe/Paris', to the formatter, * rejecting the zone ID if it is a {@code ZoneOffset}. *

    - * This appends an instruction to format/parse the zone ID to the builder - * only if it is a region-based ID. + * This appends an instruction to format only region-based zone IDs to the builder. *

    * During formatting, the zone is obtained using a mechanism equivalent * to querying the temporal with {@link TemporalQueries#zoneId()}. @@ -1148,14 +1147,14 @@ public DateTimeFormatterBuilder appendZoneId() { * During parsing, the text must match a known zone or offset. * There are two types of zone ID, offset-based, such as '+01:30' and * region-based, such as 'Europe/London'. These are parsed differently. - * If the parse starts with '+', '-', 'UT', 'UTC' or 'GMT', then the parser - * expects an offset-based zone and will not match region-based zones. - * The offset ID, such as '+02:30', may be at the start of the parse, - * or prefixed by 'UT', 'UTC' or 'GMT'. The offset ID parsing is - * equivalent to using {@link #appendOffset(String, String)} using the - * arguments 'HH:MM:ss' and the no offset string '0'. - * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser cannot - * match a following offset ID, then {@link ZoneOffset#UTC} is selected. + * If the parse starts with '+' or '-', then the parser expects an + * offset-based zone and will not match region-based zones. The offset + * ID parsing is equivalent to using {@link #appendOffset(String, String)} + * using the arguments 'HH:MM:ss' and the no offset string '0'. + * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser can + * match a following offset, then a region-based zone with the parsed + * offset will be returned, or else if the parser cannot match a following + * offset, then {@link ZoneOffset#UTC} is selected. * In all other cases, the list of known region-based zones is used to * find the longest available match. If no match is found, and the parse * starts with 'Z', then {@code ZoneOffset.UTC} is selected. @@ -1169,9 +1168,9 @@ public DateTimeFormatterBuilder appendZoneId() { * "UTC" -- ZoneId.of("UTC") * "GMT" -- ZoneId.of("GMT") * "+01:30" -- ZoneOffset.of("+01:30") - * "UT+01:30" -- ZoneOffset.of("+01:30") - * "UTC+01:30" -- ZoneOffset.of("+01:30") - * "GMT+01:30" -- ZoneOffset.of("+01:30") + * "UT+01:30" -- ZoneId.of("UT+01:30") + * "UTC+01:30" -- ZoneId.of("UTC+01:30") + * "GMT+01:30" -- ZoneId.of("GMT+01:30") * *

    * Note that this method is identical to {@code appendZoneId()} except @@ -1206,14 +1205,14 @@ public DateTimeFormatterBuilder appendZoneRegionId() { * During parsing, the text must match a known zone or offset. * There are two types of zone ID, offset-based, such as '+01:30' and * region-based, such as 'Europe/London'. These are parsed differently. - * If the parse starts with '+', '-', 'UT', 'UTC' or 'GMT', then the parser - * expects an offset-based zone and will not match region-based zones. - * The offset ID, such as '+02:30', may be at the start of the parse, - * or prefixed by 'UT', 'UTC' or 'GMT'. The offset ID parsing is - * equivalent to using {@link #appendOffset(String, String)} using the - * arguments 'HH:MM:ss' and the no offset string '0'. - * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser cannot - * match a following offset ID, then {@link ZoneOffset#UTC} is selected. + * If the parse starts with '+' or '-', then the parser expects an + * offset-based zone and will not match region-based zones. The offset + * ID parsing is equivalent to using {@link #appendOffset(String, String)} + * using the arguments 'HH:MM:ss' and the no offset string '0'. + * If the parse starts with 'UT', 'UTC' or 'GMT', and the parser can + * match a following offset, then a region-based zone with the parsed + * offset will be returned, or else if the parser cannot match a following + * offset, then {@link ZoneOffset#UTC} is selected. * In all other cases, the list of known region-based zones is used to * find the longest available match. If no match is found, and the parse * starts with 'Z', then {@code ZoneOffset.UTC} is selected. @@ -1227,9 +1226,9 @@ public DateTimeFormatterBuilder appendZoneRegionId() { * "UTC" -- ZoneId.of("UTC") * "GMT" -- ZoneId.of("GMT") * "+01:30" -- ZoneOffset.of("+01:30") - * "UT+01:30" -- ZoneOffset.of("UT+01:30") - * "UTC+01:30" -- ZoneOffset.of("UTC+01:30") - * "GMT+01:30" -- ZoneOffset.of("GMT+01:30") + * "UT+01:30" -- ZoneId.of("UT+01:30") + * "UTC+01:30" -- ZoneId.of("UTC+01:30") + * "GMT+01:30" -- ZoneId.of("GMT+01:30") * *

    * Note that this method is identical to {@code appendZoneId()} except diff --git a/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java b/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java index 5ee4c5c23c8..5be33551c70 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java +++ b/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, 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 @@ -309,7 +309,15 @@ public Iterator> getTextIterator(Chronology chrono, Temporal private Object findStore(TemporalField field, Locale locale) { Entry key = createEntry(field, locale); - return CACHE.computeIfAbsent(key, e -> createStore(e.getKey(), e.getValue())); + Object store = CACHE.get(key); + if (store == null) { + store = createStore(field, locale); + var existing = CACHE.putIfAbsent(key, store); + if (existing != null) { + store = existing; + } + } + return store; } private static int toWeekDay(int calWeekDay) { diff --git a/src/java.base/share/classes/java/time/format/DecimalStyle.java b/src/java.base/share/classes/java/time/format/DecimalStyle.java index b2513888790..a9ad8a4e273 100644 --- a/src/java.base/share/classes/java/time/format/DecimalStyle.java +++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, 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 @@ -160,7 +160,15 @@ public static DecimalStyle ofDefaultLocale() { */ public static DecimalStyle of(Locale locale) { Objects.requireNonNull(locale, "locale"); - return CACHE.computeIfAbsent(locale, DecimalStyle::create); + DecimalStyle info = CACHE.get(locale); + if (info == null) { + info = create(locale); + var existing = CACHE.putIfAbsent(locale, info); + if (existing != null) { + info = existing; + } + } + return info; } private static DecimalStyle create(Locale locale) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index a52881b047b..9ccaf92b8d6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -145,12 +145,17 @@ private NativeMemorySegmentImpl reinterpretInternal(Class callerClass, long n Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret", false); Utils.checkNonNegativeArgument(newSize, "newSize"); if (!isNative()) throw new UnsupportedOperationException("Not a native segment"); - Runnable action = cleanup != null ? - () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) : - null; + Runnable action = cleanupAction(address(), newSize, cleanup); return SegmentFactories.makeNativeSegmentUnchecked(address(), newSize, scope, readOnly, action); } + // Using a static helper method ensures there is no unintended lambda capturing of `this` + private static Runnable cleanupAction(long address, long newSize, Consumer cleanup) { + return cleanup != null ? + () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address, newSize)) : + null; + } + private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { return dup(offset, newSize, readOnly, scope); } @@ -486,9 +491,18 @@ public int characteristics() { @Override public String toString() { - return "MemorySegment{ " + - heapBase().map(hb -> "heapBase: " + hb + ", ").orElse("") + - "address: " + Utils.toHexString(address()) + + final String kind; + if (this instanceof HeapMemorySegmentImpl) { + kind = "heap"; + } else if (this instanceof MappedMemorySegmentImpl) { + kind = "mapped"; + } else { + kind = "native"; + } + return "MemorySegment{ kind: " + + kind + + heapBase().map(hb -> ", heapBase: " + hb).orElse("") + + ", address: " + Utils.toHexString(address()) + ", byteSize: " + length + " }"; } diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 2904f665732..66e6267367c 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -197,14 +197,6 @@ jdk.jlink; exports jdk.internal.logger to java.logging; - exports jdk.internal.org.objectweb.asm to - jdk.jfr; - exports jdk.internal.org.objectweb.asm.tree to - jdk.jfr; - exports jdk.internal.org.objectweb.asm.util to - jdk.jfr; - exports jdk.internal.org.objectweb.asm.commons to - jdk.jfr; exports jdk.internal.org.xml.sax to jdk.jfr; exports jdk.internal.org.xml.sax.helpers to diff --git a/src/java.base/share/classes/sun/net/www/MimeTable.java b/src/java.base/share/classes/sun/net/www/MimeTable.java index eea633e94fa..5b760241671 100644 --- a/src/java.base/share/classes/sun/net/www/MimeTable.java +++ b/src/java.base/share/classes/sun/net/www/MimeTable.java @@ -25,12 +25,9 @@ package sun.net.www; -import jdk.internal.util.StaticProperty; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.net.FileNameMap; @@ -40,30 +37,22 @@ import java.util.Properties; import java.util.StringTokenizer; -public class MimeTable implements FileNameMap { +public final class MimeTable implements FileNameMap { + /** Hash mark introducing a URI fragment */ private static final int HASH_MARK = '#'; - /** Keyed by content type, returns MimeEntries */ - private final Hashtable entries = new Hashtable<>(); - /** Keyed by file extension (with the .), returns MimeEntries */ private final Hashtable extensionMap = new Hashtable<>(); - // Will be reset if in the platform-specific data file - private static String tempFileTemplate = - System.getProperty("content.types.temp.file.template", "/tmp/%s"); - - private static final String filePreamble = "sun.net.www MIME content-types table"; - - MimeTable() { + private MimeTable() { load(); } - private static class DefaultInstanceHolder { - static final MimeTable defaultInstance = getDefaultInstance(); + private static final class DefaultInstanceHolder { + private static final MimeTable defaultInstance = getDefaultInstance(); - static MimeTable getDefaultInstance() { + private static MimeTable getDefaultInstance() { final MimeTable instance = new MimeTable(); URLConnection.setFileNameMap(instance); return instance; @@ -78,15 +67,6 @@ public static MimeTable getDefaultTable() { return DefaultInstanceHolder.defaultInstance; } - public static FileNameMap loadTable() { - MimeTable mt = getDefaultTable(); - return mt; - } - - public synchronized int getSize() { - return entries.size(); - } - public synchronized String getContentTypeFor(String fileName) { MimeEntry entry = findByFileName(fileName); if (entry != null) { @@ -96,55 +76,21 @@ public synchronized String getContentTypeFor(String fileName) { } } - public synchronized void add(MimeEntry m) { - entries.put(m.getType(), m); - - String exts[] = m.getExtensions(); + private void add(MimeEntry m) { + String[] exts = m.getExtensions(); if (exts == null) { return; } - for (int i = 0; i < exts.length; i++) { - extensionMap.put(exts[i], m); + for (String ext : exts) { + extensionMap.put(ext, m); } } - public synchronized MimeEntry remove(String type) { - MimeEntry entry = entries.get(type); - return remove(entry); - } - - public synchronized MimeEntry remove(MimeEntry entry) { - String[] extensionKeys = entry.getExtensions(); - if (extensionKeys != null) { - for (int i = 0; i < extensionKeys.length; i++) { - extensionMap.remove(extensionKeys[i]); - } - } - - return entries.remove(entry.getType()); - } - - public synchronized MimeEntry find(String type) { - MimeEntry entry = entries.get(type); - if (entry == null) { - // try a wildcard lookup - Enumeration e = entries.elements(); - while (e.hasMoreElements()) { - MimeEntry wild = e.nextElement(); - if (wild.matches(type)) { - return wild; - } - } - } - - return entry; - } - /** * Extracts the file extension and uses it to look up the entry. */ - private MimeEntry findViaFileExtension(String fname) { + private MimeEntry findByFileExtension(String fname) { int i = fname.lastIndexOf('.'); // REMIND: OS specific delimiters appear here i = Math.max(i, fname.lastIndexOf('/')); @@ -155,7 +101,8 @@ private MimeEntry findViaFileExtension(String fname) { ext = fname.substring(i).toLowerCase(Locale.ROOT); } - return findByExt(ext); + return extensionMap.get(ext); + } /** @@ -166,74 +113,27 @@ private MimeEntry findViaFileExtension(String fname) { * * @return the MIME entry associated with the file name or {@code null} */ - public MimeEntry findByFileName(String fname) { - MimeEntry entry = null; + private MimeEntry findByFileName(String fname) { // If an optional fragment introduced by a hash mark is // present, then strip it and use the prefix int hashIndex = fname.lastIndexOf(HASH_MARK); if (hashIndex > 0) { - entry = findViaFileExtension(fname.substring(0, hashIndex)); + MimeEntry entry = findByFileExtension(fname.substring(0, hashIndex)); if (entry != null) { return entry; } } - assert entry == null; - // If either no optional fragment was present, or the entry was not // found with the fragment stripped, then try again with the full name - if (entry == null) { - entry = findViaFileExtension(fname); - } - - return entry; - } - - /** - * Locate a MimeEntry by the file extension that has been associated - * with it. - */ - public synchronized MimeEntry findByExt(String fileExtension) { - return extensionMap.get(fileExtension); - } - - public synchronized MimeEntry findByDescription(String description) { - Enumeration e = elements(); - while (e.hasMoreElements()) { - MimeEntry entry = e.nextElement(); - if (description.equals(entry.getDescription())) { - return entry; - } - } - - // We failed, now try treating description as type - return find(description); - } + return findByFileExtension(fname); - String getTempFileTemplate() { - return tempFileTemplate; } - public synchronized Enumeration elements() { - return entries.elements(); - } - - // For backward compatibility -- mailcap format files - // This is not currently used, but may in the future when we add ability - // to read BOTH the properties format and the mailcap format. - protected static String[] mailcapLocations = - new String[]{ - System.getProperty("user.mailcap"), - StaticProperty.userHome() + "/.mailcap", - "/etc/mailcap", - "/usr/etc/mailcap", - "/usr/local/etc/mailcap" - }; - - public synchronized void load() { + private synchronized void load() { Properties entries = new Properties(); - File file = null; + File file; InputStream in; // First try to load the user-specific table, if it exists @@ -260,12 +160,11 @@ public synchronized void load() { parse(entries); } - void parse(Properties entries) { + private void parse(Properties entries) { // first, strip out the platform-specific temp file template String tempFileTemplate = (String)entries.get("temp.file.template"); if (tempFileTemplate != null) { entries.remove("temp.file.template"); - MimeTable.tempFileTemplate = tempFileTemplate; } // now, parse the mime-type spec's @@ -304,7 +203,7 @@ void parse(Properties entries) { // associated with. // - void parse(String type, String attrs) { + private void parse(String type, String attrs) { MimeEntry newEntry = new MimeEntry(type); // REMIND handle embedded ';' and '|' and literal '"' @@ -317,7 +216,7 @@ void parse(String type, String attrs) { add(newEntry); } - void parse(String pair, MimeEntry entry) { + private static void parse(String pair, MimeEntry entry) { // REMIND add exception handling... String name = null; String value = null; @@ -337,7 +236,7 @@ void parse(String pair, MimeEntry entry) { fill(entry, name, value); } - void fill(MimeEntry entry, String name, String value) { + private static void fill(MimeEntry entry, String name, String value) { if ("description".equalsIgnoreCase(name)) { entry.setDescription(value); } @@ -357,7 +256,7 @@ else if ("file_extensions".equalsIgnoreCase(name)) { // else illegal name exception } - int getActionCode(String action) { + private static int getActionCode(String action) { for (int i = 0; i < MimeEntry.actionKeywords.length; i++) { if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) { return i; @@ -367,61 +266,4 @@ int getActionCode(String action) { return MimeEntry.UNKNOWN; } - public Properties getAsProperties() { - Properties properties = new Properties(); - Enumeration e = elements(); - while (e.hasMoreElements()) { - MimeEntry entry = e.nextElement(); - properties.put(entry.getType(), entry.toProperty()); - } - - return properties; - } - - protected boolean saveAsProperties(File file) { - try (FileOutputStream os = new FileOutputStream(file)) { - Properties properties = getAsProperties(); - properties.put("temp.file.template", tempFileTemplate); - String tag; - String user = StaticProperty.userName(); - if (user != null) { - tag = "; customized for " + user; - properties.store(os, filePreamble + tag); - } - else { - properties.store(os, filePreamble); - } - } - catch (IOException e) { - e.printStackTrace(); - return false; - } - - return true; - } - /* - * Debugging utilities - * - public void list(PrintStream out) { - Enumeration keys = entries.keys(); - while (keys.hasMoreElements()) { - String key = (String)keys.nextElement(); - MimeEntry entry = (MimeEntry)entries.get(key); - out.println(key + ": " + entry); - } - } - - public static void main(String[] args) { - MimeTable testTable = MimeTable.getDefaultTable(); - - Enumeration e = testTable.elements(); - while (e.hasMoreElements()) { - MimeEntry entry = (MimeEntry)e.nextElement(); - System.out.println(entry); - } - - testTable.save(File.separator + "tmp" + - File.separator + "mime_table.save"); - } - */ } diff --git a/src/java.base/share/classes/sun/nio/ch/ThreadPool.java b/src/java.base/share/classes/sun/nio/ch/ThreadPool.java index 92aee323823..38a49567c15 100644 --- a/src/java.base/share/classes/sun/nio/ch/ThreadPool.java +++ b/src/java.base/share/classes/sun/nio/ch/ThreadPool.java @@ -70,7 +70,7 @@ int poolSize() { static ThreadFactory defaultThreadFactory() { return (Runnable r) -> { - Thread t = new Thread(r); + Thread t = InnocuousThread.newThread(r); t.setDaemon(true); return t; }; diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java index e2ac950f01d..29c07223988 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java @@ -25,9 +25,10 @@ package sun.nio.fs; -import java.nio.file.*; import java.io.IOException; +import java.nio.file.*; import java.util.*; +import jdk.internal.misc.InnocuousThread; /** * Base implementation of background poller thread used in watch service @@ -53,11 +54,7 @@ protected AbstractPoller() { * Starts the poller thread */ public void start() { - Thread thr = new Thread(null, - this, - "FileSystemWatchService", - 0, - false); + Thread thr = InnocuousThread.newThread("FileSystemWatchService", this); thr.setDaemon(true); thr.start(); } diff --git a/src/java.base/share/classes/sun/nio/fs/Cancellable.java b/src/java.base/share/classes/sun/nio/fs/Cancellable.java index 5e3ff43a7b0..df3c95abcc9 100644 --- a/src/java.base/share/classes/sun/nio/fs/Cancellable.java +++ b/src/java.base/share/classes/sun/nio/fs/Cancellable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,15 @@ package sun.nio.fs; -import jdk.internal.misc.Unsafe; import java.util.concurrent.ExecutionException; +import jdk.internal.misc.InnocuousThread; +import jdk.internal.misc.Unsafe; /** * Base implementation of a task (typically native) that polls a memory location * during execution so that it may be aborted/cancelled before completion. The - * task is executed by invoking the {@link runInterruptibly} method defined - * here and cancelled by invoking Thread.interrupt. + * task is executed by invoking the {@linkplain #runInterruptibly} method + * defined here and cancelled by invoking Thread.interrupt. */ abstract class Cancellable implements Runnable { @@ -117,7 +118,7 @@ public final void run() { * thread by writing into the memory location that it polls cooperatively. */ static void runInterruptibly(Cancellable task) throws ExecutionException { - Thread t = new Thread(null, task, "NIO-Task", 0, false); + Thread t = InnocuousThread.newThread("CancellableOp", task); t.start(); boolean cancelledByInterrupt = false; while (t.isAlive()) { diff --git a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java index 0284156ca3b..da486231a1d 100644 --- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java +++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java @@ -47,6 +47,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import jdk.internal.misc.InnocuousThread; import static java.nio.file.LinkOption.NOFOLLOW_LINKS; /** @@ -73,7 +74,7 @@ class PollingWatchService .newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { - Thread t = new Thread(null, r, "FileSystemWatcher", 0, false); + Thread t = InnocuousThread.newThread("FileSystemWatcher", r); t.setDaemon(true); return t; }}); diff --git a/src/java.base/share/data/tzdata/solar87 b/src/java.base/share/data/tzdata/solar87 deleted file mode 100644 index 0512ca410c1..00000000000 --- a/src/java.base/share/data/tzdata/solar87 +++ /dev/null @@ -1,413 +0,0 @@ -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -#

    -# This file is in the public domain, so clarified as of
    -# 2009-05-17 by Arthur David Olson.
    -
    -# So much for footnotes about Saudi Arabia.
    -# Apparent noon times below are for Riyadh; your mileage will vary.
    -# Times were computed using formulas in the U.S. Naval Observatory's
    -# Almanac for Computers 1987; the formulas "will give EqT to an accuracy of
    -# [plus or minus two] seconds during the current year."
    -#
    -# Rounding to the nearest five seconds results in fewer than
    -# 256 different "time types"--a limit that's faced because time types are
    -# stored on disk as unsigned chars.
    -
    -# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	sol87	1987	only	-	Jan	1	12:03:20s -0:03:20 -
    -Rule	sol87	1987	only	-	Jan	2	12:03:50s -0:03:50 -
    -Rule	sol87	1987	only	-	Jan	3	12:04:15s -0:04:15 -
    -Rule	sol87	1987	only	-	Jan	4	12:04:45s -0:04:45 -
    -Rule	sol87	1987	only	-	Jan	5	12:05:10s -0:05:10 -
    -Rule	sol87	1987	only	-	Jan	6	12:05:40s -0:05:40 -
    -Rule	sol87	1987	only	-	Jan	7	12:06:05s -0:06:05 -
    -Rule	sol87	1987	only	-	Jan	8	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Jan	9	12:06:55s -0:06:55 -
    -Rule	sol87	1987	only	-	Jan	10	12:07:20s -0:07:20 -
    -Rule	sol87	1987	only	-	Jan	11	12:07:45s -0:07:45 -
    -Rule	sol87	1987	only	-	Jan	12	12:08:10s -0:08:10 -
    -Rule	sol87	1987	only	-	Jan	13	12:08:30s -0:08:30 -
    -Rule	sol87	1987	only	-	Jan	14	12:08:55s -0:08:55 -
    -Rule	sol87	1987	only	-	Jan	15	12:09:15s -0:09:15 -
    -Rule	sol87	1987	only	-	Jan	16	12:09:35s -0:09:35 -
    -Rule	sol87	1987	only	-	Jan	17	12:09:55s -0:09:55 -
    -Rule	sol87	1987	only	-	Jan	18	12:10:15s -0:10:15 -
    -Rule	sol87	1987	only	-	Jan	19	12:10:35s -0:10:35 -
    -Rule	sol87	1987	only	-	Jan	20	12:10:55s -0:10:55 -
    -Rule	sol87	1987	only	-	Jan	21	12:11:10s -0:11:10 -
    -Rule	sol87	1987	only	-	Jan	22	12:11:30s -0:11:30 -
    -Rule	sol87	1987	only	-	Jan	23	12:11:45s -0:11:45 -
    -Rule	sol87	1987	only	-	Jan	24	12:12:00s -0:12:00 -
    -Rule	sol87	1987	only	-	Jan	25	12:12:15s -0:12:15 -
    -Rule	sol87	1987	only	-	Jan	26	12:12:30s -0:12:30 -
    -Rule	sol87	1987	only	-	Jan	27	12:12:40s -0:12:40 -
    -Rule	sol87	1987	only	-	Jan	28	12:12:55s -0:12:55 -
    -Rule	sol87	1987	only	-	Jan	29	12:13:05s -0:13:05 -
    -Rule	sol87	1987	only	-	Jan	30	12:13:15s -0:13:15 -
    -Rule	sol87	1987	only	-	Jan	31	12:13:25s -0:13:25 -
    -Rule	sol87	1987	only	-	Feb	1	12:13:35s -0:13:35 -
    -Rule	sol87	1987	only	-	Feb	2	12:13:40s -0:13:40 -
    -Rule	sol87	1987	only	-	Feb	3	12:13:50s -0:13:50 -
    -Rule	sol87	1987	only	-	Feb	4	12:13:55s -0:13:55 -
    -Rule	sol87	1987	only	-	Feb	5	12:14:00s -0:14:00 -
    -Rule	sol87	1987	only	-	Feb	6	12:14:05s -0:14:05 -
    -Rule	sol87	1987	only	-	Feb	7	12:14:10s -0:14:10 -
    -Rule	sol87	1987	only	-	Feb	8	12:14:10s -0:14:10 -
    -Rule	sol87	1987	only	-	Feb	9	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	10	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	11	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	12	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	13	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	14	12:14:15s -0:14:15 -
    -Rule	sol87	1987	only	-	Feb	15	12:14:10s -0:14:10 -
    -Rule	sol87	1987	only	-	Feb	16	12:14:10s -0:14:10 -
    -Rule	sol87	1987	only	-	Feb	17	12:14:05s -0:14:05 -
    -Rule	sol87	1987	only	-	Feb	18	12:14:00s -0:14:00 -
    -Rule	sol87	1987	only	-	Feb	19	12:13:55s -0:13:55 -
    -Rule	sol87	1987	only	-	Feb	20	12:13:50s -0:13:50 -
    -Rule	sol87	1987	only	-	Feb	21	12:13:45s -0:13:45 -
    -Rule	sol87	1987	only	-	Feb	22	12:13:35s -0:13:35 -
    -Rule	sol87	1987	only	-	Feb	23	12:13:30s -0:13:30 -
    -Rule	sol87	1987	only	-	Feb	24	12:13:20s -0:13:20 -
    -Rule	sol87	1987	only	-	Feb	25	12:13:10s -0:13:10 -
    -Rule	sol87	1987	only	-	Feb	26	12:13:00s -0:13:00 -
    -Rule	sol87	1987	only	-	Feb	27	12:12:50s -0:12:50 -
    -Rule	sol87	1987	only	-	Feb	28	12:12:40s -0:12:40 -
    -Rule	sol87	1987	only	-	Mar	1	12:12:30s -0:12:30 -
    -Rule	sol87	1987	only	-	Mar	2	12:12:20s -0:12:20 -
    -Rule	sol87	1987	only	-	Mar	3	12:12:05s -0:12:05 -
    -Rule	sol87	1987	only	-	Mar	4	12:11:55s -0:11:55 -
    -Rule	sol87	1987	only	-	Mar	5	12:11:40s -0:11:40 -
    -Rule	sol87	1987	only	-	Mar	6	12:11:25s -0:11:25 -
    -Rule	sol87	1987	only	-	Mar	7	12:11:15s -0:11:15 -
    -Rule	sol87	1987	only	-	Mar	8	12:11:00s -0:11:00 -
    -Rule	sol87	1987	only	-	Mar	9	12:10:45s -0:10:45 -
    -Rule	sol87	1987	only	-	Mar	10	12:10:30s -0:10:30 -
    -Rule	sol87	1987	only	-	Mar	11	12:10:15s -0:10:15 -
    -Rule	sol87	1987	only	-	Mar	12	12:09:55s -0:09:55 -
    -Rule	sol87	1987	only	-	Mar	13	12:09:40s -0:09:40 -
    -Rule	sol87	1987	only	-	Mar	14	12:09:25s -0:09:25 -
    -Rule	sol87	1987	only	-	Mar	15	12:09:10s -0:09:10 -
    -Rule	sol87	1987	only	-	Mar	16	12:08:50s -0:08:50 -
    -Rule	sol87	1987	only	-	Mar	17	12:08:35s -0:08:35 -
    -Rule	sol87	1987	only	-	Mar	18	12:08:15s -0:08:15 -
    -Rule	sol87	1987	only	-	Mar	19	12:08:00s -0:08:00 -
    -Rule	sol87	1987	only	-	Mar	20	12:07:40s -0:07:40 -
    -Rule	sol87	1987	only	-	Mar	21	12:07:25s -0:07:25 -
    -Rule	sol87	1987	only	-	Mar	22	12:07:05s -0:07:05 -
    -Rule	sol87	1987	only	-	Mar	23	12:06:50s -0:06:50 -
    -Rule	sol87	1987	only	-	Mar	24	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Mar	25	12:06:10s -0:06:10 -
    -Rule	sol87	1987	only	-	Mar	26	12:05:55s -0:05:55 -
    -Rule	sol87	1987	only	-	Mar	27	12:05:35s -0:05:35 -
    -Rule	sol87	1987	only	-	Mar	28	12:05:15s -0:05:15 -
    -Rule	sol87	1987	only	-	Mar	29	12:05:00s -0:05:00 -
    -Rule	sol87	1987	only	-	Mar	30	12:04:40s -0:04:40 -
    -Rule	sol87	1987	only	-	Mar	31	12:04:25s -0:04:25 -
    -Rule	sol87	1987	only	-	Apr	1	12:04:05s -0:04:05 -
    -Rule	sol87	1987	only	-	Apr	2	12:03:45s -0:03:45 -
    -Rule	sol87	1987	only	-	Apr	3	12:03:30s -0:03:30 -
    -Rule	sol87	1987	only	-	Apr	4	12:03:10s -0:03:10 -
    -Rule	sol87	1987	only	-	Apr	5	12:02:55s -0:02:55 -
    -Rule	sol87	1987	only	-	Apr	6	12:02:35s -0:02:35 -
    -Rule	sol87	1987	only	-	Apr	7	12:02:20s -0:02:20 -
    -Rule	sol87	1987	only	-	Apr	8	12:02:05s -0:02:05 -
    -Rule	sol87	1987	only	-	Apr	9	12:01:45s -0:01:45 -
    -Rule	sol87	1987	only	-	Apr	10	12:01:30s -0:01:30 -
    -Rule	sol87	1987	only	-	Apr	11	12:01:15s -0:01:15 -
    -Rule	sol87	1987	only	-	Apr	12	12:00:55s -0:00:55 -
    -Rule	sol87	1987	only	-	Apr	13	12:00:40s -0:00:40 -
    -Rule	sol87	1987	only	-	Apr	14	12:00:25s -0:00:25 -
    -Rule	sol87	1987	only	-	Apr	15	12:00:10s -0:00:10 -
    -Rule	sol87	1987	only	-	Apr	16	11:59:55s 0:00:05 -
    -Rule	sol87	1987	only	-	Apr	17	11:59:45s 0:00:15 -
    -Rule	sol87	1987	only	-	Apr	18	11:59:30s 0:00:30 -
    -Rule	sol87	1987	only	-	Apr	19	11:59:15s 0:00:45 -
    -Rule	sol87	1987	only	-	Apr	20	11:59:05s 0:00:55 -
    -Rule	sol87	1987	only	-	Apr	21	11:58:50s 0:01:10 -
    -Rule	sol87	1987	only	-	Apr	22	11:58:40s 0:01:20 -
    -Rule	sol87	1987	only	-	Apr	23	11:58:25s 0:01:35 -
    -Rule	sol87	1987	only	-	Apr	24	11:58:15s 0:01:45 -
    -Rule	sol87	1987	only	-	Apr	25	11:58:05s 0:01:55 -
    -Rule	sol87	1987	only	-	Apr	26	11:57:55s 0:02:05 -
    -Rule	sol87	1987	only	-	Apr	27	11:57:45s 0:02:15 -
    -Rule	sol87	1987	only	-	Apr	28	11:57:35s 0:02:25 -
    -Rule	sol87	1987	only	-	Apr	29	11:57:25s 0:02:35 -
    -Rule	sol87	1987	only	-	Apr	30	11:57:15s 0:02:45 -
    -Rule	sol87	1987	only	-	May	1	11:57:10s 0:02:50 -
    -Rule	sol87	1987	only	-	May	2	11:57:00s 0:03:00 -
    -Rule	sol87	1987	only	-	May	3	11:56:55s 0:03:05 -
    -Rule	sol87	1987	only	-	May	4	11:56:50s 0:03:10 -
    -Rule	sol87	1987	only	-	May	5	11:56:45s 0:03:15 -
    -Rule	sol87	1987	only	-	May	6	11:56:40s 0:03:20 -
    -Rule	sol87	1987	only	-	May	7	11:56:35s 0:03:25 -
    -Rule	sol87	1987	only	-	May	8	11:56:30s 0:03:30 -
    -Rule	sol87	1987	only	-	May	9	11:56:25s 0:03:35 -
    -Rule	sol87	1987	only	-	May	10	11:56:25s 0:03:35 -
    -Rule	sol87	1987	only	-	May	11	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	12	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	13	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	14	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	15	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	16	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	17	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	18	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	May	19	11:56:25s 0:03:35 -
    -Rule	sol87	1987	only	-	May	20	11:56:25s 0:03:35 -
    -Rule	sol87	1987	only	-	May	21	11:56:30s 0:03:30 -
    -Rule	sol87	1987	only	-	May	22	11:56:35s 0:03:25 -
    -Rule	sol87	1987	only	-	May	23	11:56:40s 0:03:20 -
    -Rule	sol87	1987	only	-	May	24	11:56:45s 0:03:15 -
    -Rule	sol87	1987	only	-	May	25	11:56:50s 0:03:10 -
    -Rule	sol87	1987	only	-	May	26	11:56:55s 0:03:05 -
    -Rule	sol87	1987	only	-	May	27	11:57:00s 0:03:00 -
    -Rule	sol87	1987	only	-	May	28	11:57:10s 0:02:50 -
    -Rule	sol87	1987	only	-	May	29	11:57:15s 0:02:45 -
    -Rule	sol87	1987	only	-	May	30	11:57:25s 0:02:35 -
    -Rule	sol87	1987	only	-	May	31	11:57:30s 0:02:30 -
    -Rule	sol87	1987	only	-	Jun	1	11:57:40s 0:02:20 -
    -Rule	sol87	1987	only	-	Jun	2	11:57:50s 0:02:10 -
    -Rule	sol87	1987	only	-	Jun	3	11:58:00s 0:02:00 -
    -Rule	sol87	1987	only	-	Jun	4	11:58:10s 0:01:50 -
    -Rule	sol87	1987	only	-	Jun	5	11:58:20s 0:01:40 -
    -Rule	sol87	1987	only	-	Jun	6	11:58:30s 0:01:30 -
    -Rule	sol87	1987	only	-	Jun	7	11:58:40s 0:01:20 -
    -Rule	sol87	1987	only	-	Jun	8	11:58:50s 0:01:10 -
    -Rule	sol87	1987	only	-	Jun	9	11:59:05s 0:00:55 -
    -Rule	sol87	1987	only	-	Jun	10	11:59:15s 0:00:45 -
    -Rule	sol87	1987	only	-	Jun	11	11:59:30s 0:00:30 -
    -Rule	sol87	1987	only	-	Jun	12	11:59:40s 0:00:20 -
    -Rule	sol87	1987	only	-	Jun	13	11:59:50s 0:00:10 -
    -Rule	sol87	1987	only	-	Jun	14	12:00:05s -0:00:05 -
    -Rule	sol87	1987	only	-	Jun	15	12:00:15s -0:00:15 -
    -Rule	sol87	1987	only	-	Jun	16	12:00:30s -0:00:30 -
    -Rule	sol87	1987	only	-	Jun	17	12:00:45s -0:00:45 -
    -Rule	sol87	1987	only	-	Jun	18	12:00:55s -0:00:55 -
    -Rule	sol87	1987	only	-	Jun	19	12:01:10s -0:01:10 -
    -Rule	sol87	1987	only	-	Jun	20	12:01:20s -0:01:20 -
    -Rule	sol87	1987	only	-	Jun	21	12:01:35s -0:01:35 -
    -Rule	sol87	1987	only	-	Jun	22	12:01:50s -0:01:50 -
    -Rule	sol87	1987	only	-	Jun	23	12:02:00s -0:02:00 -
    -Rule	sol87	1987	only	-	Jun	24	12:02:15s -0:02:15 -
    -Rule	sol87	1987	only	-	Jun	25	12:02:25s -0:02:25 -
    -Rule	sol87	1987	only	-	Jun	26	12:02:40s -0:02:40 -
    -Rule	sol87	1987	only	-	Jun	27	12:02:50s -0:02:50 -
    -Rule	sol87	1987	only	-	Jun	28	12:03:05s -0:03:05 -
    -Rule	sol87	1987	only	-	Jun	29	12:03:15s -0:03:15 -
    -Rule	sol87	1987	only	-	Jun	30	12:03:30s -0:03:30 -
    -Rule	sol87	1987	only	-	Jul	1	12:03:40s -0:03:40 -
    -Rule	sol87	1987	only	-	Jul	2	12:03:50s -0:03:50 -
    -Rule	sol87	1987	only	-	Jul	3	12:04:05s -0:04:05 -
    -Rule	sol87	1987	only	-	Jul	4	12:04:15s -0:04:15 -
    -Rule	sol87	1987	only	-	Jul	5	12:04:25s -0:04:25 -
    -Rule	sol87	1987	only	-	Jul	6	12:04:35s -0:04:35 -
    -Rule	sol87	1987	only	-	Jul	7	12:04:45s -0:04:45 -
    -Rule	sol87	1987	only	-	Jul	8	12:04:55s -0:04:55 -
    -Rule	sol87	1987	only	-	Jul	9	12:05:05s -0:05:05 -
    -Rule	sol87	1987	only	-	Jul	10	12:05:15s -0:05:15 -
    -Rule	sol87	1987	only	-	Jul	11	12:05:20s -0:05:20 -
    -Rule	sol87	1987	only	-	Jul	12	12:05:30s -0:05:30 -
    -Rule	sol87	1987	only	-	Jul	13	12:05:40s -0:05:40 -
    -Rule	sol87	1987	only	-	Jul	14	12:05:45s -0:05:45 -
    -Rule	sol87	1987	only	-	Jul	15	12:05:50s -0:05:50 -
    -Rule	sol87	1987	only	-	Jul	16	12:06:00s -0:06:00 -
    -Rule	sol87	1987	only	-	Jul	17	12:06:05s -0:06:05 -
    -Rule	sol87	1987	only	-	Jul	18	12:06:10s -0:06:10 -
    -Rule	sol87	1987	only	-	Jul	19	12:06:15s -0:06:15 -
    -Rule	sol87	1987	only	-	Jul	20	12:06:15s -0:06:15 -
    -Rule	sol87	1987	only	-	Jul	21	12:06:20s -0:06:20 -
    -Rule	sol87	1987	only	-	Jul	22	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Jul	23	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Jul	24	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Jul	25	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Jul	26	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Jul	27	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Jul	28	12:06:30s -0:06:30 -
    -Rule	sol87	1987	only	-	Jul	29	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Jul	30	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Jul	31	12:06:25s -0:06:25 -
    -Rule	sol87	1987	only	-	Aug	1	12:06:20s -0:06:20 -
    -Rule	sol87	1987	only	-	Aug	2	12:06:15s -0:06:15 -
    -Rule	sol87	1987	only	-	Aug	3	12:06:10s -0:06:10 -
    -Rule	sol87	1987	only	-	Aug	4	12:06:05s -0:06:05 -
    -Rule	sol87	1987	only	-	Aug	5	12:06:00s -0:06:00 -
    -Rule	sol87	1987	only	-	Aug	6	12:05:55s -0:05:55 -
    -Rule	sol87	1987	only	-	Aug	7	12:05:50s -0:05:50 -
    -Rule	sol87	1987	only	-	Aug	8	12:05:40s -0:05:40 -
    -Rule	sol87	1987	only	-	Aug	9	12:05:35s -0:05:35 -
    -Rule	sol87	1987	only	-	Aug	10	12:05:25s -0:05:25 -
    -Rule	sol87	1987	only	-	Aug	11	12:05:15s -0:05:15 -
    -Rule	sol87	1987	only	-	Aug	12	12:05:05s -0:05:05 -
    -Rule	sol87	1987	only	-	Aug	13	12:04:55s -0:04:55 -
    -Rule	sol87	1987	only	-	Aug	14	12:04:45s -0:04:45 -
    -Rule	sol87	1987	only	-	Aug	15	12:04:35s -0:04:35 -
    -Rule	sol87	1987	only	-	Aug	16	12:04:25s -0:04:25 -
    -Rule	sol87	1987	only	-	Aug	17	12:04:10s -0:04:10 -
    -Rule	sol87	1987	only	-	Aug	18	12:04:00s -0:04:00 -
    -Rule	sol87	1987	only	-	Aug	19	12:03:45s -0:03:45 -
    -Rule	sol87	1987	only	-	Aug	20	12:03:30s -0:03:30 -
    -Rule	sol87	1987	only	-	Aug	21	12:03:15s -0:03:15 -
    -Rule	sol87	1987	only	-	Aug	22	12:03:00s -0:03:00 -
    -Rule	sol87	1987	only	-	Aug	23	12:02:45s -0:02:45 -
    -Rule	sol87	1987	only	-	Aug	24	12:02:30s -0:02:30 -
    -Rule	sol87	1987	only	-	Aug	25	12:02:15s -0:02:15 -
    -Rule	sol87	1987	only	-	Aug	26	12:02:00s -0:02:00 -
    -Rule	sol87	1987	only	-	Aug	27	12:01:40s -0:01:40 -
    -Rule	sol87	1987	only	-	Aug	28	12:01:25s -0:01:25 -
    -Rule	sol87	1987	only	-	Aug	29	12:01:05s -0:01:05 -
    -Rule	sol87	1987	only	-	Aug	30	12:00:50s -0:00:50 -
    -Rule	sol87	1987	only	-	Aug	31	12:00:30s -0:00:30 -
    -Rule	sol87	1987	only	-	Sep	1	12:00:10s -0:00:10 -
    -Rule	sol87	1987	only	-	Sep	2	11:59:50s 0:00:10 -
    -Rule	sol87	1987	only	-	Sep	3	11:59:35s 0:00:25 -
    -Rule	sol87	1987	only	-	Sep	4	11:59:15s 0:00:45 -
    -Rule	sol87	1987	only	-	Sep	5	11:58:55s 0:01:05 -
    -Rule	sol87	1987	only	-	Sep	6	11:58:35s 0:01:25 -
    -Rule	sol87	1987	only	-	Sep	7	11:58:15s 0:01:45 -
    -Rule	sol87	1987	only	-	Sep	8	11:57:55s 0:02:05 -
    -Rule	sol87	1987	only	-	Sep	9	11:57:30s 0:02:30 -
    -Rule	sol87	1987	only	-	Sep	10	11:57:10s 0:02:50 -
    -Rule	sol87	1987	only	-	Sep	11	11:56:50s 0:03:10 -
    -Rule	sol87	1987	only	-	Sep	12	11:56:30s 0:03:30 -
    -Rule	sol87	1987	only	-	Sep	13	11:56:10s 0:03:50 -
    -Rule	sol87	1987	only	-	Sep	14	11:55:45s 0:04:15 -
    -Rule	sol87	1987	only	-	Sep	15	11:55:25s 0:04:35 -
    -Rule	sol87	1987	only	-	Sep	16	11:55:05s 0:04:55 -
    -Rule	sol87	1987	only	-	Sep	17	11:54:45s 0:05:15 -
    -Rule	sol87	1987	only	-	Sep	18	11:54:20s 0:05:40 -
    -Rule	sol87	1987	only	-	Sep	19	11:54:00s 0:06:00 -
    -Rule	sol87	1987	only	-	Sep	20	11:53:40s 0:06:20 -
    -Rule	sol87	1987	only	-	Sep	21	11:53:15s 0:06:45 -
    -Rule	sol87	1987	only	-	Sep	22	11:52:55s 0:07:05 -
    -Rule	sol87	1987	only	-	Sep	23	11:52:35s 0:07:25 -
    -Rule	sol87	1987	only	-	Sep	24	11:52:15s 0:07:45 -
    -Rule	sol87	1987	only	-	Sep	25	11:51:55s 0:08:05 -
    -Rule	sol87	1987	only	-	Sep	26	11:51:35s 0:08:25 -
    -Rule	sol87	1987	only	-	Sep	27	11:51:10s 0:08:50 -
    -Rule	sol87	1987	only	-	Sep	28	11:50:50s 0:09:10 -
    -Rule	sol87	1987	only	-	Sep	29	11:50:30s 0:09:30 -
    -Rule	sol87	1987	only	-	Sep	30	11:50:10s 0:09:50 -
    -Rule	sol87	1987	only	-	Oct	1	11:49:50s 0:10:10 -
    -Rule	sol87	1987	only	-	Oct	2	11:49:35s 0:10:25 -
    -Rule	sol87	1987	only	-	Oct	3	11:49:15s 0:10:45 -
    -Rule	sol87	1987	only	-	Oct	4	11:48:55s 0:11:05 -
    -Rule	sol87	1987	only	-	Oct	5	11:48:35s 0:11:25 -
    -Rule	sol87	1987	only	-	Oct	6	11:48:20s 0:11:40 -
    -Rule	sol87	1987	only	-	Oct	7	11:48:00s 0:12:00 -
    -Rule	sol87	1987	only	-	Oct	8	11:47:45s 0:12:15 -
    -Rule	sol87	1987	only	-	Oct	9	11:47:25s 0:12:35 -
    -Rule	sol87	1987	only	-	Oct	10	11:47:10s 0:12:50 -
    -Rule	sol87	1987	only	-	Oct	11	11:46:55s 0:13:05 -
    -Rule	sol87	1987	only	-	Oct	12	11:46:40s 0:13:20 -
    -Rule	sol87	1987	only	-	Oct	13	11:46:25s 0:13:35 -
    -Rule	sol87	1987	only	-	Oct	14	11:46:10s 0:13:50 -
    -Rule	sol87	1987	only	-	Oct	15	11:45:55s 0:14:05 -
    -Rule	sol87	1987	only	-	Oct	16	11:45:45s 0:14:15 -
    -Rule	sol87	1987	only	-	Oct	17	11:45:30s 0:14:30 -
    -Rule	sol87	1987	only	-	Oct	18	11:45:20s 0:14:40 -
    -Rule	sol87	1987	only	-	Oct	19	11:45:05s 0:14:55 -
    -Rule	sol87	1987	only	-	Oct	20	11:44:55s 0:15:05 -
    -Rule	sol87	1987	only	-	Oct	21	11:44:45s 0:15:15 -
    -Rule	sol87	1987	only	-	Oct	22	11:44:35s 0:15:25 -
    -Rule	sol87	1987	only	-	Oct	23	11:44:25s 0:15:35 -
    -Rule	sol87	1987	only	-	Oct	24	11:44:20s 0:15:40 -
    -Rule	sol87	1987	only	-	Oct	25	11:44:10s 0:15:50 -
    -Rule	sol87	1987	only	-	Oct	26	11:44:05s 0:15:55 -
    -Rule	sol87	1987	only	-	Oct	27	11:43:55s 0:16:05 -
    -Rule	sol87	1987	only	-	Oct	28	11:43:50s 0:16:10 -
    -Rule	sol87	1987	only	-	Oct	29	11:43:45s 0:16:15 -
    -Rule	sol87	1987	only	-	Oct	30	11:43:45s 0:16:15 -
    -Rule	sol87	1987	only	-	Oct	31	11:43:40s 0:16:20 -
    -Rule	sol87	1987	only	-	Nov	1	11:43:40s 0:16:20 -
    -Rule	sol87	1987	only	-	Nov	2	11:43:35s 0:16:25 -
    -Rule	sol87	1987	only	-	Nov	3	11:43:35s 0:16:25 -
    -Rule	sol87	1987	only	-	Nov	4	11:43:35s 0:16:25 -
    -Rule	sol87	1987	only	-	Nov	5	11:43:35s 0:16:25 -
    -Rule	sol87	1987	only	-	Nov	6	11:43:40s 0:16:20 -
    -Rule	sol87	1987	only	-	Nov	7	11:43:40s 0:16:20 -
    -Rule	sol87	1987	only	-	Nov	8	11:43:45s 0:16:15 -
    -Rule	sol87	1987	only	-	Nov	9	11:43:50s 0:16:10 -
    -Rule	sol87	1987	only	-	Nov	10	11:43:55s 0:16:05 -
    -Rule	sol87	1987	only	-	Nov	11	11:44:00s 0:16:00 -
    -Rule	sol87	1987	only	-	Nov	12	11:44:05s 0:15:55 -
    -Rule	sol87	1987	only	-	Nov	13	11:44:15s 0:15:45 -
    -Rule	sol87	1987	only	-	Nov	14	11:44:20s 0:15:40 -
    -Rule	sol87	1987	only	-	Nov	15	11:44:30s 0:15:30 -
    -Rule	sol87	1987	only	-	Nov	16	11:44:40s 0:15:20 -
    -Rule	sol87	1987	only	-	Nov	17	11:44:50s 0:15:10 -
    -Rule	sol87	1987	only	-	Nov	18	11:45:05s 0:14:55 -
    -Rule	sol87	1987	only	-	Nov	19	11:45:15s 0:14:45 -
    -Rule	sol87	1987	only	-	Nov	20	11:45:30s 0:14:30 -
    -Rule	sol87	1987	only	-	Nov	21	11:45:45s 0:14:15 -
    -Rule	sol87	1987	only	-	Nov	22	11:46:00s 0:14:00 -
    -Rule	sol87	1987	only	-	Nov	23	11:46:15s 0:13:45 -
    -Rule	sol87	1987	only	-	Nov	24	11:46:30s 0:13:30 -
    -Rule	sol87	1987	only	-	Nov	25	11:46:50s 0:13:10 -
    -Rule	sol87	1987	only	-	Nov	26	11:47:10s 0:12:50 -
    -Rule	sol87	1987	only	-	Nov	27	11:47:25s 0:12:35 -
    -Rule	sol87	1987	only	-	Nov	28	11:47:45s 0:12:15 -
    -Rule	sol87	1987	only	-	Nov	29	11:48:05s 0:11:55 -
    -Rule	sol87	1987	only	-	Nov	30	11:48:30s 0:11:30 -
    -Rule	sol87	1987	only	-	Dec	1	11:48:50s 0:11:10 -
    -Rule	sol87	1987	only	-	Dec	2	11:49:10s 0:10:50 -
    -Rule	sol87	1987	only	-	Dec	3	11:49:35s 0:10:25 -
    -Rule	sol87	1987	only	-	Dec	4	11:50:00s 0:10:00 -
    -Rule	sol87	1987	only	-	Dec	5	11:50:25s 0:09:35 -
    -Rule	sol87	1987	only	-	Dec	6	11:50:50s 0:09:10 -
    -Rule	sol87	1987	only	-	Dec	7	11:51:15s 0:08:45 -
    -Rule	sol87	1987	only	-	Dec	8	11:51:40s 0:08:20 -
    -Rule	sol87	1987	only	-	Dec	9	11:52:05s 0:07:55 -
    -Rule	sol87	1987	only	-	Dec	10	11:52:30s 0:07:30 -
    -Rule	sol87	1987	only	-	Dec	11	11:53:00s 0:07:00 -
    -Rule	sol87	1987	only	-	Dec	12	11:53:25s 0:06:35 -
    -Rule	sol87	1987	only	-	Dec	13	11:53:55s 0:06:05 -
    -Rule	sol87	1987	only	-	Dec	14	11:54:25s 0:05:35 -
    -Rule	sol87	1987	only	-	Dec	15	11:54:50s 0:05:10 -
    -Rule	sol87	1987	only	-	Dec	16	11:55:20s 0:04:40 -
    -Rule	sol87	1987	only	-	Dec	17	11:55:50s 0:04:10 -
    -Rule	sol87	1987	only	-	Dec	18	11:56:20s 0:03:40 -
    -Rule	sol87	1987	only	-	Dec	19	11:56:50s 0:03:10 -
    -Rule	sol87	1987	only	-	Dec	20	11:57:20s 0:02:40 -
    -Rule	sol87	1987	only	-	Dec	21	11:57:50s 0:02:10 -
    -Rule	sol87	1987	only	-	Dec	22	11:58:20s 0:01:40 -
    -Rule	sol87	1987	only	-	Dec	23	11:58:50s 0:01:10 -
    -Rule	sol87	1987	only	-	Dec	24	11:59:20s 0:00:40 -
    -Rule	sol87	1987	only	-	Dec	25	11:59:50s 0:00:10 -
    -Rule	sol87	1987	only	-	Dec	26	12:00:20s -0:00:20 -
    -Rule	sol87	1987	only	-	Dec	27	12:00:45s -0:00:45 -
    -Rule	sol87	1987	only	-	Dec	28	12:01:15s -0:01:15 -
    -Rule	sol87	1987	only	-	Dec	29	12:01:45s -0:01:45 -
    -Rule	sol87	1987	only	-	Dec	30	12:02:15s -0:02:15 -
    -Rule	sol87	1987	only	-	Dec	31	12:02:45s -0:02:45 -
    -
    -# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    -# Before and after 1987, we'll operate on local mean solar time.
    -
    -# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    -Zone	Asia/Riyadh87	3:07:04	-		zzz	1987
    -			3:07:04	sol87		zzz	1988
    -			3:07:04	-		zzz
    -# For backward compatibility...
    -Link	Asia/Riyadh87	Mideast/Riyadh87
    diff --git a/src/java.base/share/data/tzdata/solar88 b/src/java.base/share/data/tzdata/solar88
    deleted file mode 100644
    index 3314cb1d640..00000000000
    --- a/src/java.base/share/data/tzdata/solar88
    +++ /dev/null
    @@ -1,413 +0,0 @@
    -#
    -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    -#
    -# This code is free software; you can redistribute it and/or modify it
    -# under the terms of the GNU General Public License version 2 only, as
    -# published by the Free Software Foundation.  Oracle designates this
    -# particular file as subject to the "Classpath" exception as provided
    -# by Oracle in the LICENSE file that accompanied this code.
    -#
    -# This code is distributed in the hope that it will be useful, but WITHOUT
    -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    -# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    -# version 2 for more details (a copy is included in the LICENSE file that
    -# accompanied this code).
    -#
    -# You should have received a copy of the GNU General Public License version
    -# 2 along with this work; if not, write to the Free Software Foundation,
    -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    -#
    -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    -# or visit www.oracle.com if you need additional information or have any
    -# questions.
    -#
    -# 
    -# This file is in the public domain, so clarified as of
    -# 2009-05-17 by Arthur David Olson.
    -
    -# Apparent noon times below are for Riyadh; they're a bit off for other places.
    -# Times were computed using formulas in the U.S. Naval Observatory's
    -# Almanac for Computers 1988; the formulas "will give EqT to an accuracy of
    -# [plus or minus two] seconds during the current year."
    -#
    -# Rounding to the nearest five seconds results in fewer than
    -# 256 different "time types"--a limit that's faced because time types are
    -# stored on disk as unsigned chars.
    -
    -# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	sol88	1988	only	-	Jan	1	12:03:15s -0:03:15 -
    -Rule	sol88	1988	only	-	Jan	2	12:03:40s -0:03:40 -
    -Rule	sol88	1988	only	-	Jan	3	12:04:10s -0:04:10 -
    -Rule	sol88	1988	only	-	Jan	4	12:04:40s -0:04:40 -
    -Rule	sol88	1988	only	-	Jan	5	12:05:05s -0:05:05 -
    -Rule	sol88	1988	only	-	Jan	6	12:05:30s -0:05:30 -
    -Rule	sol88	1988	only	-	Jan	7	12:06:00s -0:06:00 -
    -Rule	sol88	1988	only	-	Jan	8	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jan	9	12:06:50s -0:06:50 -
    -Rule	sol88	1988	only	-	Jan	10	12:07:15s -0:07:15 -
    -Rule	sol88	1988	only	-	Jan	11	12:07:40s -0:07:40 -
    -Rule	sol88	1988	only	-	Jan	12	12:08:05s -0:08:05 -
    -Rule	sol88	1988	only	-	Jan	13	12:08:25s -0:08:25 -
    -Rule	sol88	1988	only	-	Jan	14	12:08:50s -0:08:50 -
    -Rule	sol88	1988	only	-	Jan	15	12:09:10s -0:09:10 -
    -Rule	sol88	1988	only	-	Jan	16	12:09:30s -0:09:30 -
    -Rule	sol88	1988	only	-	Jan	17	12:09:50s -0:09:50 -
    -Rule	sol88	1988	only	-	Jan	18	12:10:10s -0:10:10 -
    -Rule	sol88	1988	only	-	Jan	19	12:10:30s -0:10:30 -
    -Rule	sol88	1988	only	-	Jan	20	12:10:50s -0:10:50 -
    -Rule	sol88	1988	only	-	Jan	21	12:11:05s -0:11:05 -
    -Rule	sol88	1988	only	-	Jan	22	12:11:25s -0:11:25 -
    -Rule	sol88	1988	only	-	Jan	23	12:11:40s -0:11:40 -
    -Rule	sol88	1988	only	-	Jan	24	12:11:55s -0:11:55 -
    -Rule	sol88	1988	only	-	Jan	25	12:12:10s -0:12:10 -
    -Rule	sol88	1988	only	-	Jan	26	12:12:25s -0:12:25 -
    -Rule	sol88	1988	only	-	Jan	27	12:12:40s -0:12:40 -
    -Rule	sol88	1988	only	-	Jan	28	12:12:50s -0:12:50 -
    -Rule	sol88	1988	only	-	Jan	29	12:13:00s -0:13:00 -
    -Rule	sol88	1988	only	-	Jan	30	12:13:10s -0:13:10 -
    -Rule	sol88	1988	only	-	Jan	31	12:13:20s -0:13:20 -
    -Rule	sol88	1988	only	-	Feb	1	12:13:30s -0:13:30 -
    -Rule	sol88	1988	only	-	Feb	2	12:13:40s -0:13:40 -
    -Rule	sol88	1988	only	-	Feb	3	12:13:45s -0:13:45 -
    -Rule	sol88	1988	only	-	Feb	4	12:13:55s -0:13:55 -
    -Rule	sol88	1988	only	-	Feb	5	12:14:00s -0:14:00 -
    -Rule	sol88	1988	only	-	Feb	6	12:14:05s -0:14:05 -
    -Rule	sol88	1988	only	-	Feb	7	12:14:10s -0:14:10 -
    -Rule	sol88	1988	only	-	Feb	8	12:14:10s -0:14:10 -
    -Rule	sol88	1988	only	-	Feb	9	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	10	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	11	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	12	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	13	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	14	12:14:15s -0:14:15 -
    -Rule	sol88	1988	only	-	Feb	15	12:14:10s -0:14:10 -
    -Rule	sol88	1988	only	-	Feb	16	12:14:10s -0:14:10 -
    -Rule	sol88	1988	only	-	Feb	17	12:14:05s -0:14:05 -
    -Rule	sol88	1988	only	-	Feb	18	12:14:00s -0:14:00 -
    -Rule	sol88	1988	only	-	Feb	19	12:13:55s -0:13:55 -
    -Rule	sol88	1988	only	-	Feb	20	12:13:50s -0:13:50 -
    -Rule	sol88	1988	only	-	Feb	21	12:13:45s -0:13:45 -
    -Rule	sol88	1988	only	-	Feb	22	12:13:40s -0:13:40 -
    -Rule	sol88	1988	only	-	Feb	23	12:13:30s -0:13:30 -
    -Rule	sol88	1988	only	-	Feb	24	12:13:20s -0:13:20 -
    -Rule	sol88	1988	only	-	Feb	25	12:13:15s -0:13:15 -
    -Rule	sol88	1988	only	-	Feb	26	12:13:05s -0:13:05 -
    -Rule	sol88	1988	only	-	Feb	27	12:12:55s -0:12:55 -
    -Rule	sol88	1988	only	-	Feb	28	12:12:45s -0:12:45 -
    -Rule	sol88	1988	only	-	Feb	29	12:12:30s -0:12:30 -
    -Rule	sol88	1988	only	-	Mar	1	12:12:20s -0:12:20 -
    -Rule	sol88	1988	only	-	Mar	2	12:12:10s -0:12:10 -
    -Rule	sol88	1988	only	-	Mar	3	12:11:55s -0:11:55 -
    -Rule	sol88	1988	only	-	Mar	4	12:11:45s -0:11:45 -
    -Rule	sol88	1988	only	-	Mar	5	12:11:30s -0:11:30 -
    -Rule	sol88	1988	only	-	Mar	6	12:11:15s -0:11:15 -
    -Rule	sol88	1988	only	-	Mar	7	12:11:00s -0:11:00 -
    -Rule	sol88	1988	only	-	Mar	8	12:10:45s -0:10:45 -
    -Rule	sol88	1988	only	-	Mar	9	12:10:30s -0:10:30 -
    -Rule	sol88	1988	only	-	Mar	10	12:10:15s -0:10:15 -
    -Rule	sol88	1988	only	-	Mar	11	12:10:00s -0:10:00 -
    -Rule	sol88	1988	only	-	Mar	12	12:09:45s -0:09:45 -
    -Rule	sol88	1988	only	-	Mar	13	12:09:30s -0:09:30 -
    -Rule	sol88	1988	only	-	Mar	14	12:09:10s -0:09:10 -
    -Rule	sol88	1988	only	-	Mar	15	12:08:55s -0:08:55 -
    -Rule	sol88	1988	only	-	Mar	16	12:08:40s -0:08:40 -
    -Rule	sol88	1988	only	-	Mar	17	12:08:20s -0:08:20 -
    -Rule	sol88	1988	only	-	Mar	18	12:08:05s -0:08:05 -
    -Rule	sol88	1988	only	-	Mar	19	12:07:45s -0:07:45 -
    -Rule	sol88	1988	only	-	Mar	20	12:07:30s -0:07:30 -
    -Rule	sol88	1988	only	-	Mar	21	12:07:10s -0:07:10 -
    -Rule	sol88	1988	only	-	Mar	22	12:06:50s -0:06:50 -
    -Rule	sol88	1988	only	-	Mar	23	12:06:35s -0:06:35 -
    -Rule	sol88	1988	only	-	Mar	24	12:06:15s -0:06:15 -
    -Rule	sol88	1988	only	-	Mar	25	12:06:00s -0:06:00 -
    -Rule	sol88	1988	only	-	Mar	26	12:05:40s -0:05:40 -
    -Rule	sol88	1988	only	-	Mar	27	12:05:20s -0:05:20 -
    -Rule	sol88	1988	only	-	Mar	28	12:05:05s -0:05:05 -
    -Rule	sol88	1988	only	-	Mar	29	12:04:45s -0:04:45 -
    -Rule	sol88	1988	only	-	Mar	30	12:04:25s -0:04:25 -
    -Rule	sol88	1988	only	-	Mar	31	12:04:10s -0:04:10 -
    -Rule	sol88	1988	only	-	Apr	1	12:03:50s -0:03:50 -
    -Rule	sol88	1988	only	-	Apr	2	12:03:35s -0:03:35 -
    -Rule	sol88	1988	only	-	Apr	3	12:03:15s -0:03:15 -
    -Rule	sol88	1988	only	-	Apr	4	12:03:00s -0:03:00 -
    -Rule	sol88	1988	only	-	Apr	5	12:02:40s -0:02:40 -
    -Rule	sol88	1988	only	-	Apr	6	12:02:25s -0:02:25 -
    -Rule	sol88	1988	only	-	Apr	7	12:02:05s -0:02:05 -
    -Rule	sol88	1988	only	-	Apr	8	12:01:50s -0:01:50 -
    -Rule	sol88	1988	only	-	Apr	9	12:01:35s -0:01:35 -
    -Rule	sol88	1988	only	-	Apr	10	12:01:15s -0:01:15 -
    -Rule	sol88	1988	only	-	Apr	11	12:01:00s -0:01:00 -
    -Rule	sol88	1988	only	-	Apr	12	12:00:45s -0:00:45 -
    -Rule	sol88	1988	only	-	Apr	13	12:00:30s -0:00:30 -
    -Rule	sol88	1988	only	-	Apr	14	12:00:15s -0:00:15 -
    -Rule	sol88	1988	only	-	Apr	15	12:00:00s 0:00:00 -
    -Rule	sol88	1988	only	-	Apr	16	11:59:45s 0:00:15 -
    -Rule	sol88	1988	only	-	Apr	17	11:59:30s 0:00:30 -
    -Rule	sol88	1988	only	-	Apr	18	11:59:20s 0:00:40 -
    -Rule	sol88	1988	only	-	Apr	19	11:59:05s 0:00:55 -
    -Rule	sol88	1988	only	-	Apr	20	11:58:55s 0:01:05 -
    -Rule	sol88	1988	only	-	Apr	21	11:58:40s 0:01:20 -
    -Rule	sol88	1988	only	-	Apr	22	11:58:30s 0:01:30 -
    -Rule	sol88	1988	only	-	Apr	23	11:58:15s 0:01:45 -
    -Rule	sol88	1988	only	-	Apr	24	11:58:05s 0:01:55 -
    -Rule	sol88	1988	only	-	Apr	25	11:57:55s 0:02:05 -
    -Rule	sol88	1988	only	-	Apr	26	11:57:45s 0:02:15 -
    -Rule	sol88	1988	only	-	Apr	27	11:57:35s 0:02:25 -
    -Rule	sol88	1988	only	-	Apr	28	11:57:30s 0:02:30 -
    -Rule	sol88	1988	only	-	Apr	29	11:57:20s 0:02:40 -
    -Rule	sol88	1988	only	-	Apr	30	11:57:10s 0:02:50 -
    -Rule	sol88	1988	only	-	May	1	11:57:05s 0:02:55 -
    -Rule	sol88	1988	only	-	May	2	11:56:55s 0:03:05 -
    -Rule	sol88	1988	only	-	May	3	11:56:50s 0:03:10 -
    -Rule	sol88	1988	only	-	May	4	11:56:45s 0:03:15 -
    -Rule	sol88	1988	only	-	May	5	11:56:40s 0:03:20 -
    -Rule	sol88	1988	only	-	May	6	11:56:35s 0:03:25 -
    -Rule	sol88	1988	only	-	May	7	11:56:30s 0:03:30 -
    -Rule	sol88	1988	only	-	May	8	11:56:25s 0:03:35 -
    -Rule	sol88	1988	only	-	May	9	11:56:25s 0:03:35 -
    -Rule	sol88	1988	only	-	May	10	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	11	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	12	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	13	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	14	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	15	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	16	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	17	11:56:20s 0:03:40 -
    -Rule	sol88	1988	only	-	May	18	11:56:25s 0:03:35 -
    -Rule	sol88	1988	only	-	May	19	11:56:25s 0:03:35 -
    -Rule	sol88	1988	only	-	May	20	11:56:30s 0:03:30 -
    -Rule	sol88	1988	only	-	May	21	11:56:35s 0:03:25 -
    -Rule	sol88	1988	only	-	May	22	11:56:40s 0:03:20 -
    -Rule	sol88	1988	only	-	May	23	11:56:45s 0:03:15 -
    -Rule	sol88	1988	only	-	May	24	11:56:50s 0:03:10 -
    -Rule	sol88	1988	only	-	May	25	11:56:55s 0:03:05 -
    -Rule	sol88	1988	only	-	May	26	11:57:00s 0:03:00 -
    -Rule	sol88	1988	only	-	May	27	11:57:05s 0:02:55 -
    -Rule	sol88	1988	only	-	May	28	11:57:15s 0:02:45 -
    -Rule	sol88	1988	only	-	May	29	11:57:20s 0:02:40 -
    -Rule	sol88	1988	only	-	May	30	11:57:30s 0:02:30 -
    -Rule	sol88	1988	only	-	May	31	11:57:40s 0:02:20 -
    -Rule	sol88	1988	only	-	Jun	1	11:57:50s 0:02:10 -
    -Rule	sol88	1988	only	-	Jun	2	11:57:55s 0:02:05 -
    -Rule	sol88	1988	only	-	Jun	3	11:58:05s 0:01:55 -
    -Rule	sol88	1988	only	-	Jun	4	11:58:15s 0:01:45 -
    -Rule	sol88	1988	only	-	Jun	5	11:58:30s 0:01:30 -
    -Rule	sol88	1988	only	-	Jun	6	11:58:40s 0:01:20 -
    -Rule	sol88	1988	only	-	Jun	7	11:58:50s 0:01:10 -
    -Rule	sol88	1988	only	-	Jun	8	11:59:00s 0:01:00 -
    -Rule	sol88	1988	only	-	Jun	9	11:59:15s 0:00:45 -
    -Rule	sol88	1988	only	-	Jun	10	11:59:25s 0:00:35 -
    -Rule	sol88	1988	only	-	Jun	11	11:59:35s 0:00:25 -
    -Rule	sol88	1988	only	-	Jun	12	11:59:50s 0:00:10 -
    -Rule	sol88	1988	only	-	Jun	13	12:00:00s 0:00:00 -
    -Rule	sol88	1988	only	-	Jun	14	12:00:15s -0:00:15 -
    -Rule	sol88	1988	only	-	Jun	15	12:00:25s -0:00:25 -
    -Rule	sol88	1988	only	-	Jun	16	12:00:40s -0:00:40 -
    -Rule	sol88	1988	only	-	Jun	17	12:00:55s -0:00:55 -
    -Rule	sol88	1988	only	-	Jun	18	12:01:05s -0:01:05 -
    -Rule	sol88	1988	only	-	Jun	19	12:01:20s -0:01:20 -
    -Rule	sol88	1988	only	-	Jun	20	12:01:30s -0:01:30 -
    -Rule	sol88	1988	only	-	Jun	21	12:01:45s -0:01:45 -
    -Rule	sol88	1988	only	-	Jun	22	12:02:00s -0:02:00 -
    -Rule	sol88	1988	only	-	Jun	23	12:02:10s -0:02:10 -
    -Rule	sol88	1988	only	-	Jun	24	12:02:25s -0:02:25 -
    -Rule	sol88	1988	only	-	Jun	25	12:02:35s -0:02:35 -
    -Rule	sol88	1988	only	-	Jun	26	12:02:50s -0:02:50 -
    -Rule	sol88	1988	only	-	Jun	27	12:03:00s -0:03:00 -
    -Rule	sol88	1988	only	-	Jun	28	12:03:15s -0:03:15 -
    -Rule	sol88	1988	only	-	Jun	29	12:03:25s -0:03:25 -
    -Rule	sol88	1988	only	-	Jun	30	12:03:40s -0:03:40 -
    -Rule	sol88	1988	only	-	Jul	1	12:03:50s -0:03:50 -
    -Rule	sol88	1988	only	-	Jul	2	12:04:00s -0:04:00 -
    -Rule	sol88	1988	only	-	Jul	3	12:04:10s -0:04:10 -
    -Rule	sol88	1988	only	-	Jul	4	12:04:25s -0:04:25 -
    -Rule	sol88	1988	only	-	Jul	5	12:04:35s -0:04:35 -
    -Rule	sol88	1988	only	-	Jul	6	12:04:45s -0:04:45 -
    -Rule	sol88	1988	only	-	Jul	7	12:04:55s -0:04:55 -
    -Rule	sol88	1988	only	-	Jul	8	12:05:05s -0:05:05 -
    -Rule	sol88	1988	only	-	Jul	9	12:05:10s -0:05:10 -
    -Rule	sol88	1988	only	-	Jul	10	12:05:20s -0:05:20 -
    -Rule	sol88	1988	only	-	Jul	11	12:05:30s -0:05:30 -
    -Rule	sol88	1988	only	-	Jul	12	12:05:35s -0:05:35 -
    -Rule	sol88	1988	only	-	Jul	13	12:05:45s -0:05:45 -
    -Rule	sol88	1988	only	-	Jul	14	12:05:50s -0:05:50 -
    -Rule	sol88	1988	only	-	Jul	15	12:05:55s -0:05:55 -
    -Rule	sol88	1988	only	-	Jul	16	12:06:00s -0:06:00 -
    -Rule	sol88	1988	only	-	Jul	17	12:06:05s -0:06:05 -
    -Rule	sol88	1988	only	-	Jul	18	12:06:10s -0:06:10 -
    -Rule	sol88	1988	only	-	Jul	19	12:06:15s -0:06:15 -
    -Rule	sol88	1988	only	-	Jul	20	12:06:20s -0:06:20 -
    -Rule	sol88	1988	only	-	Jul	21	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jul	22	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jul	23	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jul	24	12:06:30s -0:06:30 -
    -Rule	sol88	1988	only	-	Jul	25	12:06:30s -0:06:30 -
    -Rule	sol88	1988	only	-	Jul	26	12:06:30s -0:06:30 -
    -Rule	sol88	1988	only	-	Jul	27	12:06:30s -0:06:30 -
    -Rule	sol88	1988	only	-	Jul	28	12:06:30s -0:06:30 -
    -Rule	sol88	1988	only	-	Jul	29	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jul	30	12:06:25s -0:06:25 -
    -Rule	sol88	1988	only	-	Jul	31	12:06:20s -0:06:20 -
    -Rule	sol88	1988	only	-	Aug	1	12:06:15s -0:06:15 -
    -Rule	sol88	1988	only	-	Aug	2	12:06:15s -0:06:15 -
    -Rule	sol88	1988	only	-	Aug	3	12:06:10s -0:06:10 -
    -Rule	sol88	1988	only	-	Aug	4	12:06:05s -0:06:05 -
    -Rule	sol88	1988	only	-	Aug	5	12:05:55s -0:05:55 -
    -Rule	sol88	1988	only	-	Aug	6	12:05:50s -0:05:50 -
    -Rule	sol88	1988	only	-	Aug	7	12:05:45s -0:05:45 -
    -Rule	sol88	1988	only	-	Aug	8	12:05:35s -0:05:35 -
    -Rule	sol88	1988	only	-	Aug	9	12:05:25s -0:05:25 -
    -Rule	sol88	1988	only	-	Aug	10	12:05:20s -0:05:20 -
    -Rule	sol88	1988	only	-	Aug	11	12:05:10s -0:05:10 -
    -Rule	sol88	1988	only	-	Aug	12	12:05:00s -0:05:00 -
    -Rule	sol88	1988	only	-	Aug	13	12:04:50s -0:04:50 -
    -Rule	sol88	1988	only	-	Aug	14	12:04:35s -0:04:35 -
    -Rule	sol88	1988	only	-	Aug	15	12:04:25s -0:04:25 -
    -Rule	sol88	1988	only	-	Aug	16	12:04:15s -0:04:15 -
    -Rule	sol88	1988	only	-	Aug	17	12:04:00s -0:04:00 -
    -Rule	sol88	1988	only	-	Aug	18	12:03:50s -0:03:50 -
    -Rule	sol88	1988	only	-	Aug	19	12:03:35s -0:03:35 -
    -Rule	sol88	1988	only	-	Aug	20	12:03:20s -0:03:20 -
    -Rule	sol88	1988	only	-	Aug	21	12:03:05s -0:03:05 -
    -Rule	sol88	1988	only	-	Aug	22	12:02:50s -0:02:50 -
    -Rule	sol88	1988	only	-	Aug	23	12:02:35s -0:02:35 -
    -Rule	sol88	1988	only	-	Aug	24	12:02:20s -0:02:20 -
    -Rule	sol88	1988	only	-	Aug	25	12:02:00s -0:02:00 -
    -Rule	sol88	1988	only	-	Aug	26	12:01:45s -0:01:45 -
    -Rule	sol88	1988	only	-	Aug	27	12:01:30s -0:01:30 -
    -Rule	sol88	1988	only	-	Aug	28	12:01:10s -0:01:10 -
    -Rule	sol88	1988	only	-	Aug	29	12:00:50s -0:00:50 -
    -Rule	sol88	1988	only	-	Aug	30	12:00:35s -0:00:35 -
    -Rule	sol88	1988	only	-	Aug	31	12:00:15s -0:00:15 -
    -Rule	sol88	1988	only	-	Sep	1	11:59:55s 0:00:05 -
    -Rule	sol88	1988	only	-	Sep	2	11:59:35s 0:00:25 -
    -Rule	sol88	1988	only	-	Sep	3	11:59:20s 0:00:40 -
    -Rule	sol88	1988	only	-	Sep	4	11:59:00s 0:01:00 -
    -Rule	sol88	1988	only	-	Sep	5	11:58:40s 0:01:20 -
    -Rule	sol88	1988	only	-	Sep	6	11:58:20s 0:01:40 -
    -Rule	sol88	1988	only	-	Sep	7	11:58:00s 0:02:00 -
    -Rule	sol88	1988	only	-	Sep	8	11:57:35s 0:02:25 -
    -Rule	sol88	1988	only	-	Sep	9	11:57:15s 0:02:45 -
    -Rule	sol88	1988	only	-	Sep	10	11:56:55s 0:03:05 -
    -Rule	sol88	1988	only	-	Sep	11	11:56:35s 0:03:25 -
    -Rule	sol88	1988	only	-	Sep	12	11:56:15s 0:03:45 -
    -Rule	sol88	1988	only	-	Sep	13	11:55:50s 0:04:10 -
    -Rule	sol88	1988	only	-	Sep	14	11:55:30s 0:04:30 -
    -Rule	sol88	1988	only	-	Sep	15	11:55:10s 0:04:50 -
    -Rule	sol88	1988	only	-	Sep	16	11:54:50s 0:05:10 -
    -Rule	sol88	1988	only	-	Sep	17	11:54:25s 0:05:35 -
    -Rule	sol88	1988	only	-	Sep	18	11:54:05s 0:05:55 -
    -Rule	sol88	1988	only	-	Sep	19	11:53:45s 0:06:15 -
    -Rule	sol88	1988	only	-	Sep	20	11:53:25s 0:06:35 -
    -Rule	sol88	1988	only	-	Sep	21	11:53:00s 0:07:00 -
    -Rule	sol88	1988	only	-	Sep	22	11:52:40s 0:07:20 -
    -Rule	sol88	1988	only	-	Sep	23	11:52:20s 0:07:40 -
    -Rule	sol88	1988	only	-	Sep	24	11:52:00s 0:08:00 -
    -Rule	sol88	1988	only	-	Sep	25	11:51:40s 0:08:20 -
    -Rule	sol88	1988	only	-	Sep	26	11:51:15s 0:08:45 -
    -Rule	sol88	1988	only	-	Sep	27	11:50:55s 0:09:05 -
    -Rule	sol88	1988	only	-	Sep	28	11:50:35s 0:09:25 -
    -Rule	sol88	1988	only	-	Sep	29	11:50:15s 0:09:45 -
    -Rule	sol88	1988	only	-	Sep	30	11:49:55s 0:10:05 -
    -Rule	sol88	1988	only	-	Oct	1	11:49:35s 0:10:25 -
    -Rule	sol88	1988	only	-	Oct	2	11:49:20s 0:10:40 -
    -Rule	sol88	1988	only	-	Oct	3	11:49:00s 0:11:00 -
    -Rule	sol88	1988	only	-	Oct	4	11:48:40s 0:11:20 -
    -Rule	sol88	1988	only	-	Oct	5	11:48:25s 0:11:35 -
    -Rule	sol88	1988	only	-	Oct	6	11:48:05s 0:11:55 -
    -Rule	sol88	1988	only	-	Oct	7	11:47:50s 0:12:10 -
    -Rule	sol88	1988	only	-	Oct	8	11:47:30s 0:12:30 -
    -Rule	sol88	1988	only	-	Oct	9	11:47:15s 0:12:45 -
    -Rule	sol88	1988	only	-	Oct	10	11:47:00s 0:13:00 -
    -Rule	sol88	1988	only	-	Oct	11	11:46:45s 0:13:15 -
    -Rule	sol88	1988	only	-	Oct	12	11:46:30s 0:13:30 -
    -Rule	sol88	1988	only	-	Oct	13	11:46:15s 0:13:45 -
    -Rule	sol88	1988	only	-	Oct	14	11:46:00s 0:14:00 -
    -Rule	sol88	1988	only	-	Oct	15	11:45:45s 0:14:15 -
    -Rule	sol88	1988	only	-	Oct	16	11:45:35s 0:14:25 -
    -Rule	sol88	1988	only	-	Oct	17	11:45:20s 0:14:40 -
    -Rule	sol88	1988	only	-	Oct	18	11:45:10s 0:14:50 -
    -Rule	sol88	1988	only	-	Oct	19	11:45:00s 0:15:00 -
    -Rule	sol88	1988	only	-	Oct	20	11:44:45s 0:15:15 -
    -Rule	sol88	1988	only	-	Oct	21	11:44:40s 0:15:20 -
    -Rule	sol88	1988	only	-	Oct	22	11:44:30s 0:15:30 -
    -Rule	sol88	1988	only	-	Oct	23	11:44:20s 0:15:40 -
    -Rule	sol88	1988	only	-	Oct	24	11:44:10s 0:15:50 -
    -Rule	sol88	1988	only	-	Oct	25	11:44:05s 0:15:55 -
    -Rule	sol88	1988	only	-	Oct	26	11:44:00s 0:16:00 -
    -Rule	sol88	1988	only	-	Oct	27	11:43:55s 0:16:05 -
    -Rule	sol88	1988	only	-	Oct	28	11:43:50s 0:16:10 -
    -Rule	sol88	1988	only	-	Oct	29	11:43:45s 0:16:15 -
    -Rule	sol88	1988	only	-	Oct	30	11:43:40s 0:16:20 -
    -Rule	sol88	1988	only	-	Oct	31	11:43:40s 0:16:20 -
    -Rule	sol88	1988	only	-	Nov	1	11:43:35s 0:16:25 -
    -Rule	sol88	1988	only	-	Nov	2	11:43:35s 0:16:25 -
    -Rule	sol88	1988	only	-	Nov	3	11:43:35s 0:16:25 -
    -Rule	sol88	1988	only	-	Nov	4	11:43:35s 0:16:25 -
    -Rule	sol88	1988	only	-	Nov	5	11:43:40s 0:16:20 -
    -Rule	sol88	1988	only	-	Nov	6	11:43:40s 0:16:20 -
    -Rule	sol88	1988	only	-	Nov	7	11:43:45s 0:16:15 -
    -Rule	sol88	1988	only	-	Nov	8	11:43:45s 0:16:15 -
    -Rule	sol88	1988	only	-	Nov	9	11:43:50s 0:16:10 -
    -Rule	sol88	1988	only	-	Nov	10	11:44:00s 0:16:00 -
    -Rule	sol88	1988	only	-	Nov	11	11:44:05s 0:15:55 -
    -Rule	sol88	1988	only	-	Nov	12	11:44:10s 0:15:50 -
    -Rule	sol88	1988	only	-	Nov	13	11:44:20s 0:15:40 -
    -Rule	sol88	1988	only	-	Nov	14	11:44:30s 0:15:30 -
    -Rule	sol88	1988	only	-	Nov	15	11:44:40s 0:15:20 -
    -Rule	sol88	1988	only	-	Nov	16	11:44:50s 0:15:10 -
    -Rule	sol88	1988	only	-	Nov	17	11:45:00s 0:15:00 -
    -Rule	sol88	1988	only	-	Nov	18	11:45:15s 0:14:45 -
    -Rule	sol88	1988	only	-	Nov	19	11:45:25s 0:14:35 -
    -Rule	sol88	1988	only	-	Nov	20	11:45:40s 0:14:20 -
    -Rule	sol88	1988	only	-	Nov	21	11:45:55s 0:14:05 -
    -Rule	sol88	1988	only	-	Nov	22	11:46:10s 0:13:50 -
    -Rule	sol88	1988	only	-	Nov	23	11:46:30s 0:13:30 -
    -Rule	sol88	1988	only	-	Nov	24	11:46:45s 0:13:15 -
    -Rule	sol88	1988	only	-	Nov	25	11:47:05s 0:12:55 -
    -Rule	sol88	1988	only	-	Nov	26	11:47:20s 0:12:40 -
    -Rule	sol88	1988	only	-	Nov	27	11:47:40s 0:12:20 -
    -Rule	sol88	1988	only	-	Nov	28	11:48:00s 0:12:00 -
    -Rule	sol88	1988	only	-	Nov	29	11:48:25s 0:11:35 -
    -Rule	sol88	1988	only	-	Nov	30	11:48:45s 0:11:15 -
    -Rule	sol88	1988	only	-	Dec	1	11:49:05s 0:10:55 -
    -Rule	sol88	1988	only	-	Dec	2	11:49:30s 0:10:30 -
    -Rule	sol88	1988	only	-	Dec	3	11:49:55s 0:10:05 -
    -Rule	sol88	1988	only	-	Dec	4	11:50:15s 0:09:45 -
    -Rule	sol88	1988	only	-	Dec	5	11:50:40s 0:09:20 -
    -Rule	sol88	1988	only	-	Dec	6	11:51:05s 0:08:55 -
    -Rule	sol88	1988	only	-	Dec	7	11:51:35s 0:08:25 -
    -Rule	sol88	1988	only	-	Dec	8	11:52:00s 0:08:00 -
    -Rule	sol88	1988	only	-	Dec	9	11:52:25s 0:07:35 -
    -Rule	sol88	1988	only	-	Dec	10	11:52:55s 0:07:05 -
    -Rule	sol88	1988	only	-	Dec	11	11:53:20s 0:06:40 -
    -Rule	sol88	1988	only	-	Dec	12	11:53:50s 0:06:10 -
    -Rule	sol88	1988	only	-	Dec	13	11:54:15s 0:05:45 -
    -Rule	sol88	1988	only	-	Dec	14	11:54:45s 0:05:15 -
    -Rule	sol88	1988	only	-	Dec	15	11:55:15s 0:04:45 -
    -Rule	sol88	1988	only	-	Dec	16	11:55:45s 0:04:15 -
    -Rule	sol88	1988	only	-	Dec	17	11:56:15s 0:03:45 -
    -Rule	sol88	1988	only	-	Dec	18	11:56:40s 0:03:20 -
    -Rule	sol88	1988	only	-	Dec	19	11:57:10s 0:02:50 -
    -Rule	sol88	1988	only	-	Dec	20	11:57:40s 0:02:20 -
    -Rule	sol88	1988	only	-	Dec	21	11:58:10s 0:01:50 -
    -Rule	sol88	1988	only	-	Dec	22	11:58:40s 0:01:20 -
    -Rule	sol88	1988	only	-	Dec	23	11:59:10s 0:00:50 -
    -Rule	sol88	1988	only	-	Dec	24	11:59:40s 0:00:20 -
    -Rule	sol88	1988	only	-	Dec	25	12:00:10s -0:00:10 -
    -Rule	sol88	1988	only	-	Dec	26	12:00:40s -0:00:40 -
    -Rule	sol88	1988	only	-	Dec	27	12:01:10s -0:01:10 -
    -Rule	sol88	1988	only	-	Dec	28	12:01:40s -0:01:40 -
    -Rule	sol88	1988	only	-	Dec	29	12:02:10s -0:02:10 -
    -Rule	sol88	1988	only	-	Dec	30	12:02:35s -0:02:35 -
    -Rule	sol88	1988	only	-	Dec	31	12:03:05s -0:03:05 -
    -
    -# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    -# Before and after 1988, we'll operate on local mean solar time.
    -
    -# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    -Zone	Asia/Riyadh88	3:07:04	-		zzz	1988
    -			3:07:04	sol88		zzz	1989
    -			3:07:04	-		zzz
    -# For backward compatibility...
    -Link	Asia/Riyadh88	Mideast/Riyadh88
    diff --git a/src/java.base/share/data/tzdata/solar89 b/src/java.base/share/data/tzdata/solar89
    deleted file mode 100644
    index 3aa88cf0893..00000000000
    --- a/src/java.base/share/data/tzdata/solar89
    +++ /dev/null
    @@ -1,418 +0,0 @@
    -#
    -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    -#
    -# This code is free software; you can redistribute it and/or modify it
    -# under the terms of the GNU General Public License version 2 only, as
    -# published by the Free Software Foundation.  Oracle designates this
    -# particular file as subject to the "Classpath" exception as provided
    -# by Oracle in the LICENSE file that accompanied this code.
    -#
    -# This code is distributed in the hope that it will be useful, but WITHOUT
    -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    -# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    -# version 2 for more details (a copy is included in the LICENSE file that
    -# accompanied this code).
    -#
    -# You should have received a copy of the GNU General Public License version
    -# 2 along with this work; if not, write to the Free Software Foundation,
    -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    -#
    -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    -# or visit www.oracle.com if you need additional information or have any
    -# questions.
    -#
    -# 
    -# This file is in the public domain, so clarified as of
    -# 2009-05-17 by Arthur David Olson.
    -
    -# Apparent noon times below are for Riyadh; they're a bit off for other places.
    -# Times were computed using a formula provided by the U. S. Naval Observatory:
    -#	eqt = -105.8 * sin(l) + 596.2 * sin(2 * l) + 4.4 * sin(3 * l)
    -#		-12.7 * sin(4 * l) - 429.0 * cos(l) - 2.1 * cos (2 * l)
    -#		+ 19.3 * cos(3 * l);
    -# where l is the "mean longitude of the Sun" given by
    -#	l = 279.642 degrees + 0.985647 * d
    -# and d is the interval in days from January 0, 0 hours Universal Time
    -# (equaling the day of the year plus the fraction of a day from zero hours).
    -# The accuracy of the formula is plus or minus three seconds.
    -#
    -# Rounding to the nearest five seconds results in fewer than
    -# 256 different "time types"--a limit that's faced because time types are
    -# stored on disk as unsigned chars.
    -
    -# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    -Rule	sol89	1989	only	-	Jan	1	12:03:35s -0:03:35 -
    -Rule	sol89	1989	only	-	Jan	2	12:04:05s -0:04:05 -
    -Rule	sol89	1989	only	-	Jan	3	12:04:30s -0:04:30 -
    -Rule	sol89	1989	only	-	Jan	4	12:05:00s -0:05:00 -
    -Rule	sol89	1989	only	-	Jan	5	12:05:25s -0:05:25 -
    -Rule	sol89	1989	only	-	Jan	6	12:05:50s -0:05:50 -
    -Rule	sol89	1989	only	-	Jan	7	12:06:15s -0:06:15 -
    -Rule	sol89	1989	only	-	Jan	8	12:06:45s -0:06:45 -
    -Rule	sol89	1989	only	-	Jan	9	12:07:10s -0:07:10 -
    -Rule	sol89	1989	only	-	Jan	10	12:07:35s -0:07:35 -
    -Rule	sol89	1989	only	-	Jan	11	12:07:55s -0:07:55 -
    -Rule	sol89	1989	only	-	Jan	12	12:08:20s -0:08:20 -
    -Rule	sol89	1989	only	-	Jan	13	12:08:45s -0:08:45 -
    -Rule	sol89	1989	only	-	Jan	14	12:09:05s -0:09:05 -
    -Rule	sol89	1989	only	-	Jan	15	12:09:25s -0:09:25 -
    -Rule	sol89	1989	only	-	Jan	16	12:09:45s -0:09:45 -
    -Rule	sol89	1989	only	-	Jan	17	12:10:05s -0:10:05 -
    -Rule	sol89	1989	only	-	Jan	18	12:10:25s -0:10:25 -
    -Rule	sol89	1989	only	-	Jan	19	12:10:45s -0:10:45 -
    -Rule	sol89	1989	only	-	Jan	20	12:11:05s -0:11:05 -
    -Rule	sol89	1989	only	-	Jan	21	12:11:20s -0:11:20 -
    -Rule	sol89	1989	only	-	Jan	22	12:11:35s -0:11:35 -
    -Rule	sol89	1989	only	-	Jan	23	12:11:55s -0:11:55 -
    -Rule	sol89	1989	only	-	Jan	24	12:12:10s -0:12:10 -
    -Rule	sol89	1989	only	-	Jan	25	12:12:20s -0:12:20 -
    -Rule	sol89	1989	only	-	Jan	26	12:12:35s -0:12:35 -
    -Rule	sol89	1989	only	-	Jan	27	12:12:50s -0:12:50 -
    -Rule	sol89	1989	only	-	Jan	28	12:13:00s -0:13:00 -
    -Rule	sol89	1989	only	-	Jan	29	12:13:10s -0:13:10 -
    -Rule	sol89	1989	only	-	Jan	30	12:13:20s -0:13:20 -
    -Rule	sol89	1989	only	-	Jan	31	12:13:30s -0:13:30 -
    -Rule	sol89	1989	only	-	Feb	1	12:13:40s -0:13:40 -
    -Rule	sol89	1989	only	-	Feb	2	12:13:45s -0:13:45 -
    -Rule	sol89	1989	only	-	Feb	3	12:13:55s -0:13:55 -
    -Rule	sol89	1989	only	-	Feb	4	12:14:00s -0:14:00 -
    -Rule	sol89	1989	only	-	Feb	5	12:14:05s -0:14:05 -
    -Rule	sol89	1989	only	-	Feb	6	12:14:10s -0:14:10 -
    -Rule	sol89	1989	only	-	Feb	7	12:14:10s -0:14:10 -
    -Rule	sol89	1989	only	-	Feb	8	12:14:15s -0:14:15 -
    -Rule	sol89	1989	only	-	Feb	9	12:14:15s -0:14:15 -
    -Rule	sol89	1989	only	-	Feb	10	12:14:20s -0:14:20 -
    -Rule	sol89	1989	only	-	Feb	11	12:14:20s -0:14:20 -
    -Rule	sol89	1989	only	-	Feb	12	12:14:20s -0:14:20 -
    -Rule	sol89	1989	only	-	Feb	13	12:14:15s -0:14:15 -
    -Rule	sol89	1989	only	-	Feb	14	12:14:15s -0:14:15 -
    -Rule	sol89	1989	only	-	Feb	15	12:14:10s -0:14:10 -
    -Rule	sol89	1989	only	-	Feb	16	12:14:10s -0:14:10 -
    -Rule	sol89	1989	only	-	Feb	17	12:14:05s -0:14:05 -
    -Rule	sol89	1989	only	-	Feb	18	12:14:00s -0:14:00 -
    -Rule	sol89	1989	only	-	Feb	19	12:13:55s -0:13:55 -
    -Rule	sol89	1989	only	-	Feb	20	12:13:50s -0:13:50 -
    -Rule	sol89	1989	only	-	Feb	21	12:13:40s -0:13:40 -
    -Rule	sol89	1989	only	-	Feb	22	12:13:35s -0:13:35 -
    -Rule	sol89	1989	only	-	Feb	23	12:13:25s -0:13:25 -
    -Rule	sol89	1989	only	-	Feb	24	12:13:15s -0:13:15 -
    -Rule	sol89	1989	only	-	Feb	25	12:13:05s -0:13:05 -
    -Rule	sol89	1989	only	-	Feb	26	12:12:55s -0:12:55 -
    -Rule	sol89	1989	only	-	Feb	27	12:12:45s -0:12:45 -
    -Rule	sol89	1989	only	-	Feb	28	12:12:35s -0:12:35 -
    -Rule	sol89	1989	only	-	Mar	1	12:12:25s -0:12:25 -
    -Rule	sol89	1989	only	-	Mar	2	12:12:10s -0:12:10 -
    -Rule	sol89	1989	only	-	Mar	3	12:12:00s -0:12:00 -
    -Rule	sol89	1989	only	-	Mar	4	12:11:45s -0:11:45 -
    -Rule	sol89	1989	only	-	Mar	5	12:11:35s -0:11:35 -
    -Rule	sol89	1989	only	-	Mar	6	12:11:20s -0:11:20 -
    -Rule	sol89	1989	only	-	Mar	7	12:11:05s -0:11:05 -
    -Rule	sol89	1989	only	-	Mar	8	12:10:50s -0:10:50 -
    -Rule	sol89	1989	only	-	Mar	9	12:10:35s -0:10:35 -
    -Rule	sol89	1989	only	-	Mar	10	12:10:20s -0:10:20 -
    -Rule	sol89	1989	only	-	Mar	11	12:10:05s -0:10:05 -
    -Rule	sol89	1989	only	-	Mar	12	12:09:50s -0:09:50 -
    -Rule	sol89	1989	only	-	Mar	13	12:09:30s -0:09:30 -
    -Rule	sol89	1989	only	-	Mar	14	12:09:15s -0:09:15 -
    -Rule	sol89	1989	only	-	Mar	15	12:09:00s -0:09:00 -
    -Rule	sol89	1989	only	-	Mar	16	12:08:40s -0:08:40 -
    -Rule	sol89	1989	only	-	Mar	17	12:08:25s -0:08:25 -
    -Rule	sol89	1989	only	-	Mar	18	12:08:05s -0:08:05 -
    -Rule	sol89	1989	only	-	Mar	19	12:07:50s -0:07:50 -
    -Rule	sol89	1989	only	-	Mar	20	12:07:30s -0:07:30 -
    -Rule	sol89	1989	only	-	Mar	21	12:07:15s -0:07:15 -
    -Rule	sol89	1989	only	-	Mar	22	12:06:55s -0:06:55 -
    -Rule	sol89	1989	only	-	Mar	23	12:06:35s -0:06:35 -
    -Rule	sol89	1989	only	-	Mar	24	12:06:20s -0:06:20 -
    -Rule	sol89	1989	only	-	Mar	25	12:06:00s -0:06:00 -
    -Rule	sol89	1989	only	-	Mar	26	12:05:40s -0:05:40 -
    -Rule	sol89	1989	only	-	Mar	27	12:05:25s -0:05:25 -
    -Rule	sol89	1989	only	-	Mar	28	12:05:05s -0:05:05 -
    -Rule	sol89	1989	only	-	Mar	29	12:04:50s -0:04:50 -
    -Rule	sol89	1989	only	-	Mar	30	12:04:30s -0:04:30 -
    -Rule	sol89	1989	only	-	Mar	31	12:04:10s -0:04:10 -
    -Rule	sol89	1989	only	-	Apr	1	12:03:55s -0:03:55 -
    -Rule	sol89	1989	only	-	Apr	2	12:03:35s -0:03:35 -
    -Rule	sol89	1989	only	-	Apr	3	12:03:20s -0:03:20 -
    -Rule	sol89	1989	only	-	Apr	4	12:03:00s -0:03:00 -
    -Rule	sol89	1989	only	-	Apr	5	12:02:45s -0:02:45 -
    -Rule	sol89	1989	only	-	Apr	6	12:02:25s -0:02:25 -
    -Rule	sol89	1989	only	-	Apr	7	12:02:10s -0:02:10 -
    -Rule	sol89	1989	only	-	Apr	8	12:01:50s -0:01:50 -
    -Rule	sol89	1989	only	-	Apr	9	12:01:35s -0:01:35 -
    -Rule	sol89	1989	only	-	Apr	10	12:01:20s -0:01:20 -
    -Rule	sol89	1989	only	-	Apr	11	12:01:05s -0:01:05 -
    -Rule	sol89	1989	only	-	Apr	12	12:00:50s -0:00:50 -
    -Rule	sol89	1989	only	-	Apr	13	12:00:35s -0:00:35 -
    -Rule	sol89	1989	only	-	Apr	14	12:00:20s -0:00:20 -
    -Rule	sol89	1989	only	-	Apr	15	12:00:05s -0:00:05 -
    -Rule	sol89	1989	only	-	Apr	16	11:59:50s 0:00:10 -
    -Rule	sol89	1989	only	-	Apr	17	11:59:35s 0:00:25 -
    -Rule	sol89	1989	only	-	Apr	18	11:59:20s 0:00:40 -
    -Rule	sol89	1989	only	-	Apr	19	11:59:10s 0:00:50 -
    -Rule	sol89	1989	only	-	Apr	20	11:58:55s 0:01:05 -
    -Rule	sol89	1989	only	-	Apr	21	11:58:45s 0:01:15 -
    -Rule	sol89	1989	only	-	Apr	22	11:58:30s 0:01:30 -
    -Rule	sol89	1989	only	-	Apr	23	11:58:20s 0:01:40 -
    -Rule	sol89	1989	only	-	Apr	24	11:58:10s 0:01:50 -
    -Rule	sol89	1989	only	-	Apr	25	11:58:00s 0:02:00 -
    -Rule	sol89	1989	only	-	Apr	26	11:57:50s 0:02:10 -
    -Rule	sol89	1989	only	-	Apr	27	11:57:40s 0:02:20 -
    -Rule	sol89	1989	only	-	Apr	28	11:57:30s 0:02:30 -
    -Rule	sol89	1989	only	-	Apr	29	11:57:20s 0:02:40 -
    -Rule	sol89	1989	only	-	Apr	30	11:57:15s 0:02:45 -
    -Rule	sol89	1989	only	-	May	1	11:57:05s 0:02:55 -
    -Rule	sol89	1989	only	-	May	2	11:57:00s 0:03:00 -
    -Rule	sol89	1989	only	-	May	3	11:56:50s 0:03:10 -
    -Rule	sol89	1989	only	-	May	4	11:56:45s 0:03:15 -
    -Rule	sol89	1989	only	-	May	5	11:56:40s 0:03:20 -
    -Rule	sol89	1989	only	-	May	6	11:56:35s 0:03:25 -
    -Rule	sol89	1989	only	-	May	7	11:56:30s 0:03:30 -
    -Rule	sol89	1989	only	-	May	8	11:56:30s 0:03:30 -
    -Rule	sol89	1989	only	-	May	9	11:56:25s 0:03:35 -
    -Rule	sol89	1989	only	-	May	10	11:56:25s 0:03:35 -
    -Rule	sol89	1989	only	-	May	11	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	12	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	13	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	14	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	15	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	16	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	17	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	May	18	11:56:25s 0:03:35 -
    -Rule	sol89	1989	only	-	May	19	11:56:25s 0:03:35 -
    -Rule	sol89	1989	only	-	May	20	11:56:30s 0:03:30 -
    -Rule	sol89	1989	only	-	May	21	11:56:35s 0:03:25 -
    -Rule	sol89	1989	only	-	May	22	11:56:35s 0:03:25 -
    -Rule	sol89	1989	only	-	May	23	11:56:40s 0:03:20 -
    -Rule	sol89	1989	only	-	May	24	11:56:45s 0:03:15 -
    -Rule	sol89	1989	only	-	May	25	11:56:55s 0:03:05 -
    -Rule	sol89	1989	only	-	May	26	11:57:00s 0:03:00 -
    -Rule	sol89	1989	only	-	May	27	11:57:05s 0:02:55 -
    -Rule	sol89	1989	only	-	May	28	11:57:15s 0:02:45 -
    -Rule	sol89	1989	only	-	May	29	11:57:20s 0:02:40 -
    -Rule	sol89	1989	only	-	May	30	11:57:30s 0:02:30 -
    -Rule	sol89	1989	only	-	May	31	11:57:35s 0:02:25 -
    -Rule	sol89	1989	only	-	Jun	1	11:57:45s 0:02:15 -
    -Rule	sol89	1989	only	-	Jun	2	11:57:55s 0:02:05 -
    -Rule	sol89	1989	only	-	Jun	3	11:58:05s 0:01:55 -
    -Rule	sol89	1989	only	-	Jun	4	11:58:15s 0:01:45 -
    -Rule	sol89	1989	only	-	Jun	5	11:58:25s 0:01:35 -
    -Rule	sol89	1989	only	-	Jun	6	11:58:35s 0:01:25 -
    -Rule	sol89	1989	only	-	Jun	7	11:58:45s 0:01:15 -
    -Rule	sol89	1989	only	-	Jun	8	11:59:00s 0:01:00 -
    -Rule	sol89	1989	only	-	Jun	9	11:59:10s 0:00:50 -
    -Rule	sol89	1989	only	-	Jun	10	11:59:20s 0:00:40 -
    -Rule	sol89	1989	only	-	Jun	11	11:59:35s 0:00:25 -
    -Rule	sol89	1989	only	-	Jun	12	11:59:45s 0:00:15 -
    -Rule	sol89	1989	only	-	Jun	13	12:00:00s 0:00:00 -
    -Rule	sol89	1989	only	-	Jun	14	12:00:10s -0:00:10 -
    -Rule	sol89	1989	only	-	Jun	15	12:00:25s -0:00:25 -
    -Rule	sol89	1989	only	-	Jun	16	12:00:35s -0:00:35 -
    -Rule	sol89	1989	only	-	Jun	17	12:00:50s -0:00:50 -
    -Rule	sol89	1989	only	-	Jun	18	12:01:05s -0:01:05 -
    -Rule	sol89	1989	only	-	Jun	19	12:01:15s -0:01:15 -
    -Rule	sol89	1989	only	-	Jun	20	12:01:30s -0:01:30 -
    -Rule	sol89	1989	only	-	Jun	21	12:01:40s -0:01:40 -
    -Rule	sol89	1989	only	-	Jun	22	12:01:55s -0:01:55 -
    -Rule	sol89	1989	only	-	Jun	23	12:02:10s -0:02:10 -
    -Rule	sol89	1989	only	-	Jun	24	12:02:20s -0:02:20 -
    -Rule	sol89	1989	only	-	Jun	25	12:02:35s -0:02:35 -
    -Rule	sol89	1989	only	-	Jun	26	12:02:45s -0:02:45 -
    -Rule	sol89	1989	only	-	Jun	27	12:03:00s -0:03:00 -
    -Rule	sol89	1989	only	-	Jun	28	12:03:10s -0:03:10 -
    -Rule	sol89	1989	only	-	Jun	29	12:03:25s -0:03:25 -
    -Rule	sol89	1989	only	-	Jun	30	12:03:35s -0:03:35 -
    -Rule	sol89	1989	only	-	Jul	1	12:03:45s -0:03:45 -
    -Rule	sol89	1989	only	-	Jul	2	12:04:00s -0:04:00 -
    -Rule	sol89	1989	only	-	Jul	3	12:04:10s -0:04:10 -
    -Rule	sol89	1989	only	-	Jul	4	12:04:20s -0:04:20 -
    -Rule	sol89	1989	only	-	Jul	5	12:04:30s -0:04:30 -
    -Rule	sol89	1989	only	-	Jul	6	12:04:40s -0:04:40 -
    -Rule	sol89	1989	only	-	Jul	7	12:04:50s -0:04:50 -
    -Rule	sol89	1989	only	-	Jul	8	12:05:00s -0:05:00 -
    -Rule	sol89	1989	only	-	Jul	9	12:05:10s -0:05:10 -
    -Rule	sol89	1989	only	-	Jul	10	12:05:20s -0:05:20 -
    -Rule	sol89	1989	only	-	Jul	11	12:05:25s -0:05:25 -
    -Rule	sol89	1989	only	-	Jul	12	12:05:35s -0:05:35 -
    -Rule	sol89	1989	only	-	Jul	13	12:05:40s -0:05:40 -
    -Rule	sol89	1989	only	-	Jul	14	12:05:50s -0:05:50 -
    -Rule	sol89	1989	only	-	Jul	15	12:05:55s -0:05:55 -
    -Rule	sol89	1989	only	-	Jul	16	12:06:00s -0:06:00 -
    -Rule	sol89	1989	only	-	Jul	17	12:06:05s -0:06:05 -
    -Rule	sol89	1989	only	-	Jul	18	12:06:10s -0:06:10 -
    -Rule	sol89	1989	only	-	Jul	19	12:06:15s -0:06:15 -
    -Rule	sol89	1989	only	-	Jul	20	12:06:20s -0:06:20 -
    -Rule	sol89	1989	only	-	Jul	21	12:06:20s -0:06:20 -
    -Rule	sol89	1989	only	-	Jul	22	12:06:25s -0:06:25 -
    -Rule	sol89	1989	only	-	Jul	23	12:06:25s -0:06:25 -
    -Rule	sol89	1989	only	-	Jul	24	12:06:30s -0:06:30 -
    -Rule	sol89	1989	only	-	Jul	25	12:06:30s -0:06:30 -
    -Rule	sol89	1989	only	-	Jul	26	12:06:30s -0:06:30 -
    -Rule	sol89	1989	only	-	Jul	27	12:06:30s -0:06:30 -
    -Rule	sol89	1989	only	-	Jul	28	12:06:30s -0:06:30 -
    -Rule	sol89	1989	only	-	Jul	29	12:06:25s -0:06:25 -
    -Rule	sol89	1989	only	-	Jul	30	12:06:25s -0:06:25 -
    -Rule	sol89	1989	only	-	Jul	31	12:06:20s -0:06:20 -
    -Rule	sol89	1989	only	-	Aug	1	12:06:20s -0:06:20 -
    -Rule	sol89	1989	only	-	Aug	2	12:06:15s -0:06:15 -
    -Rule	sol89	1989	only	-	Aug	3	12:06:10s -0:06:10 -
    -Rule	sol89	1989	only	-	Aug	4	12:06:05s -0:06:05 -
    -Rule	sol89	1989	only	-	Aug	5	12:06:00s -0:06:00 -
    -Rule	sol89	1989	only	-	Aug	6	12:05:50s -0:05:50 -
    -Rule	sol89	1989	only	-	Aug	7	12:05:45s -0:05:45 -
    -Rule	sol89	1989	only	-	Aug	8	12:05:35s -0:05:35 -
    -Rule	sol89	1989	only	-	Aug	9	12:05:30s -0:05:30 -
    -Rule	sol89	1989	only	-	Aug	10	12:05:20s -0:05:20 -
    -Rule	sol89	1989	only	-	Aug	11	12:05:10s -0:05:10 -
    -Rule	sol89	1989	only	-	Aug	12	12:05:00s -0:05:00 -
    -Rule	sol89	1989	only	-	Aug	13	12:04:50s -0:04:50 -
    -Rule	sol89	1989	only	-	Aug	14	12:04:40s -0:04:40 -
    -Rule	sol89	1989	only	-	Aug	15	12:04:30s -0:04:30 -
    -Rule	sol89	1989	only	-	Aug	16	12:04:15s -0:04:15 -
    -Rule	sol89	1989	only	-	Aug	17	12:04:05s -0:04:05 -
    -Rule	sol89	1989	only	-	Aug	18	12:03:50s -0:03:50 -
    -Rule	sol89	1989	only	-	Aug	19	12:03:35s -0:03:35 -
    -Rule	sol89	1989	only	-	Aug	20	12:03:25s -0:03:25 -
    -Rule	sol89	1989	only	-	Aug	21	12:03:10s -0:03:10 -
    -Rule	sol89	1989	only	-	Aug	22	12:02:55s -0:02:55 -
    -Rule	sol89	1989	only	-	Aug	23	12:02:40s -0:02:40 -
    -Rule	sol89	1989	only	-	Aug	24	12:02:20s -0:02:20 -
    -Rule	sol89	1989	only	-	Aug	25	12:02:05s -0:02:05 -
    -Rule	sol89	1989	only	-	Aug	26	12:01:50s -0:01:50 -
    -Rule	sol89	1989	only	-	Aug	27	12:01:30s -0:01:30 -
    -Rule	sol89	1989	only	-	Aug	28	12:01:15s -0:01:15 -
    -Rule	sol89	1989	only	-	Aug	29	12:00:55s -0:00:55 -
    -Rule	sol89	1989	only	-	Aug	30	12:00:40s -0:00:40 -
    -Rule	sol89	1989	only	-	Aug	31	12:00:20s -0:00:20 -
    -Rule	sol89	1989	only	-	Sep	1	12:00:00s 0:00:00 -
    -Rule	sol89	1989	only	-	Sep	2	11:59:45s 0:00:15 -
    -Rule	sol89	1989	only	-	Sep	3	11:59:25s 0:00:35 -
    -Rule	sol89	1989	only	-	Sep	4	11:59:05s 0:00:55 -
    -Rule	sol89	1989	only	-	Sep	5	11:58:45s 0:01:15 -
    -Rule	sol89	1989	only	-	Sep	6	11:58:25s 0:01:35 -
    -Rule	sol89	1989	only	-	Sep	7	11:58:05s 0:01:55 -
    -Rule	sol89	1989	only	-	Sep	8	11:57:45s 0:02:15 -
    -Rule	sol89	1989	only	-	Sep	9	11:57:20s 0:02:40 -
    -Rule	sol89	1989	only	-	Sep	10	11:57:00s 0:03:00 -
    -Rule	sol89	1989	only	-	Sep	11	11:56:40s 0:03:20 -
    -Rule	sol89	1989	only	-	Sep	12	11:56:20s 0:03:40 -
    -Rule	sol89	1989	only	-	Sep	13	11:56:00s 0:04:00 -
    -Rule	sol89	1989	only	-	Sep	14	11:55:35s 0:04:25 -
    -Rule	sol89	1989	only	-	Sep	15	11:55:15s 0:04:45 -
    -Rule	sol89	1989	only	-	Sep	16	11:54:55s 0:05:05 -
    -Rule	sol89	1989	only	-	Sep	17	11:54:35s 0:05:25 -
    -Rule	sol89	1989	only	-	Sep	18	11:54:10s 0:05:50 -
    -Rule	sol89	1989	only	-	Sep	19	11:53:50s 0:06:10 -
    -Rule	sol89	1989	only	-	Sep	20	11:53:30s 0:06:30 -
    -Rule	sol89	1989	only	-	Sep	21	11:53:10s 0:06:50 -
    -Rule	sol89	1989	only	-	Sep	22	11:52:45s 0:07:15 -
    -Rule	sol89	1989	only	-	Sep	23	11:52:25s 0:07:35 -
    -Rule	sol89	1989	only	-	Sep	24	11:52:05s 0:07:55 -
    -Rule	sol89	1989	only	-	Sep	25	11:51:45s 0:08:15 -
    -Rule	sol89	1989	only	-	Sep	26	11:51:25s 0:08:35 -
    -Rule	sol89	1989	only	-	Sep	27	11:51:05s 0:08:55 -
    -Rule	sol89	1989	only	-	Sep	28	11:50:40s 0:09:20 -
    -Rule	sol89	1989	only	-	Sep	29	11:50:20s 0:09:40 -
    -Rule	sol89	1989	only	-	Sep	30	11:50:00s 0:10:00 -
    -Rule	sol89	1989	only	-	Oct	1	11:49:45s 0:10:15 -
    -Rule	sol89	1989	only	-	Oct	2	11:49:25s 0:10:35 -
    -Rule	sol89	1989	only	-	Oct	3	11:49:05s 0:10:55 -
    -Rule	sol89	1989	only	-	Oct	4	11:48:45s 0:11:15 -
    -Rule	sol89	1989	only	-	Oct	5	11:48:30s 0:11:30 -
    -Rule	sol89	1989	only	-	Oct	6	11:48:10s 0:11:50 -
    -Rule	sol89	1989	only	-	Oct	7	11:47:50s 0:12:10 -
    -Rule	sol89	1989	only	-	Oct	8	11:47:35s 0:12:25 -
    -Rule	sol89	1989	only	-	Oct	9	11:47:20s 0:12:40 -
    -Rule	sol89	1989	only	-	Oct	10	11:47:00s 0:13:00 -
    -Rule	sol89	1989	only	-	Oct	11	11:46:45s 0:13:15 -
    -Rule	sol89	1989	only	-	Oct	12	11:46:30s 0:13:30 -
    -Rule	sol89	1989	only	-	Oct	13	11:46:15s 0:13:45 -
    -Rule	sol89	1989	only	-	Oct	14	11:46:00s 0:14:00 -
    -Rule	sol89	1989	only	-	Oct	15	11:45:50s 0:14:10 -
    -Rule	sol89	1989	only	-	Oct	16	11:45:35s 0:14:25 -
    -Rule	sol89	1989	only	-	Oct	17	11:45:20s 0:14:40 -
    -Rule	sol89	1989	only	-	Oct	18	11:45:10s 0:14:50 -
    -Rule	sol89	1989	only	-	Oct	19	11:45:00s 0:15:00 -
    -Rule	sol89	1989	only	-	Oct	20	11:44:50s 0:15:10 -
    -Rule	sol89	1989	only	-	Oct	21	11:44:40s 0:15:20 -
    -Rule	sol89	1989	only	-	Oct	22	11:44:30s 0:15:30 -
    -Rule	sol89	1989	only	-	Oct	23	11:44:20s 0:15:40 -
    -Rule	sol89	1989	only	-	Oct	24	11:44:10s 0:15:50 -
    -Rule	sol89	1989	only	-	Oct	25	11:44:05s 0:15:55 -
    -Rule	sol89	1989	only	-	Oct	26	11:44:00s 0:16:00 -
    -Rule	sol89	1989	only	-	Oct	27	11:43:50s 0:16:10 -
    -Rule	sol89	1989	only	-	Oct	28	11:43:45s 0:16:15 -
    -Rule	sol89	1989	only	-	Oct	29	11:43:40s 0:16:20 -
    -Rule	sol89	1989	only	-	Oct	30	11:43:40s 0:16:20 -
    -Rule	sol89	1989	only	-	Oct	31	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	1	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	2	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	3	11:43:30s 0:16:30 -
    -Rule	sol89	1989	only	-	Nov	4	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	5	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	6	11:43:35s 0:16:25 -
    -Rule	sol89	1989	only	-	Nov	7	11:43:40s 0:16:20 -
    -Rule	sol89	1989	only	-	Nov	8	11:43:45s 0:16:15 -
    -Rule	sol89	1989	only	-	Nov	9	11:43:50s 0:16:10 -
    -Rule	sol89	1989	only	-	Nov	10	11:43:55s 0:16:05 -
    -Rule	sol89	1989	only	-	Nov	11	11:44:00s 0:16:00 -
    -Rule	sol89	1989	only	-	Nov	12	11:44:05s 0:15:55 -
    -Rule	sol89	1989	only	-	Nov	13	11:44:15s 0:15:45 -
    -Rule	sol89	1989	only	-	Nov	14	11:44:25s 0:15:35 -
    -Rule	sol89	1989	only	-	Nov	15	11:44:35s 0:15:25 -
    -Rule	sol89	1989	only	-	Nov	16	11:44:45s 0:15:15 -
    -Rule	sol89	1989	only	-	Nov	17	11:44:55s 0:15:05 -
    -Rule	sol89	1989	only	-	Nov	18	11:45:10s 0:14:50 -
    -Rule	sol89	1989	only	-	Nov	19	11:45:20s 0:14:40 -
    -Rule	sol89	1989	only	-	Nov	20	11:45:35s 0:14:25 -
    -Rule	sol89	1989	only	-	Nov	21	11:45:50s 0:14:10 -
    -Rule	sol89	1989	only	-	Nov	22	11:46:05s 0:13:55 -
    -Rule	sol89	1989	only	-	Nov	23	11:46:25s 0:13:35 -
    -Rule	sol89	1989	only	-	Nov	24	11:46:40s 0:13:20 -
    -Rule	sol89	1989	only	-	Nov	25	11:47:00s 0:13:00 -
    -Rule	sol89	1989	only	-	Nov	26	11:47:20s 0:12:40 -
    -Rule	sol89	1989	only	-	Nov	27	11:47:35s 0:12:25 -
    -Rule	sol89	1989	only	-	Nov	28	11:47:55s 0:12:05 -
    -Rule	sol89	1989	only	-	Nov	29	11:48:20s 0:11:40 -
    -Rule	sol89	1989	only	-	Nov	30	11:48:40s 0:11:20 -
    -Rule	sol89	1989	only	-	Dec	1	11:49:00s 0:11:00 -
    -Rule	sol89	1989	only	-	Dec	2	11:49:25s 0:10:35 -
    -Rule	sol89	1989	only	-	Dec	3	11:49:50s 0:10:10 -
    -Rule	sol89	1989	only	-	Dec	4	11:50:15s 0:09:45 -
    -Rule	sol89	1989	only	-	Dec	5	11:50:35s 0:09:25 -
    -Rule	sol89	1989	only	-	Dec	6	11:51:00s 0:09:00 -
    -Rule	sol89	1989	only	-	Dec	7	11:51:30s 0:08:30 -
    -Rule	sol89	1989	only	-	Dec	8	11:51:55s 0:08:05 -
    -Rule	sol89	1989	only	-	Dec	9	11:52:20s 0:07:40 -
    -Rule	sol89	1989	only	-	Dec	10	11:52:50s 0:07:10 -
    -Rule	sol89	1989	only	-	Dec	11	11:53:15s 0:06:45 -
    -Rule	sol89	1989	only	-	Dec	12	11:53:45s 0:06:15 -
    -Rule	sol89	1989	only	-	Dec	13	11:54:10s 0:05:50 -
    -Rule	sol89	1989	only	-	Dec	14	11:54:40s 0:05:20 -
    -Rule	sol89	1989	only	-	Dec	15	11:55:10s 0:04:50 -
    -Rule	sol89	1989	only	-	Dec	16	11:55:40s 0:04:20 -
    -Rule	sol89	1989	only	-	Dec	17	11:56:05s 0:03:55 -
    -Rule	sol89	1989	only	-	Dec	18	11:56:35s 0:03:25 -
    -Rule	sol89	1989	only	-	Dec	19	11:57:05s 0:02:55 -
    -Rule	sol89	1989	only	-	Dec	20	11:57:35s 0:02:25 -
    -Rule	sol89	1989	only	-	Dec	21	11:58:05s 0:01:55 -
    -Rule	sol89	1989	only	-	Dec	22	11:58:35s 0:01:25 -
    -Rule	sol89	1989	only	-	Dec	23	11:59:05s 0:00:55 -
    -Rule	sol89	1989	only	-	Dec	24	11:59:35s 0:00:25 -
    -Rule	sol89	1989	only	-	Dec	25	12:00:05s -0:00:05 -
    -Rule	sol89	1989	only	-	Dec	26	12:00:35s -0:00:35 -
    -Rule	sol89	1989	only	-	Dec	27	12:01:05s -0:01:05 -
    -Rule	sol89	1989	only	-	Dec	28	12:01:35s -0:01:35 -
    -Rule	sol89	1989	only	-	Dec	29	12:02:00s -0:02:00 -
    -Rule	sol89	1989	only	-	Dec	30	12:02:30s -0:02:30 -
    -Rule	sol89	1989	only	-	Dec	31	12:03:00s -0:03:00 -
    -
    -# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    -# Before and after 1989, we'll operate on local mean solar time.
    -
    -# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    -Zone	Asia/Riyadh89	3:07:04	-		zzz	1989
    -			3:07:04	sol89		zzz	1990
    -			3:07:04	-		zzz
    -# For backward compatibility...
    -Link	Asia/Riyadh89	Mideast/Riyadh89
    diff --git a/src/java.base/share/data/tzdata/zone.tab b/src/java.base/share/data/tzdata/zone.tab
    deleted file mode 100644
    index b90ab4e4b25..00000000000
    --- a/src/java.base/share/data/tzdata/zone.tab
    +++ /dev/null
    @@ -1,470 +0,0 @@
    -#
    -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    -#
    -# This code is free software; you can redistribute it and/or modify it
    -# under the terms of the GNU General Public License version 2 only, as
    -# published by the Free Software Foundation.  Oracle designates this
    -# particular file as subject to the "Classpath" exception as provided
    -# by Oracle in the LICENSE file that accompanied this code.
    -#
    -# This code is distributed in the hope that it will be useful, but WITHOUT
    -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    -# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    -# version 2 for more details (a copy is included in the LICENSE file that
    -# accompanied this code).
    -#
    -# You should have received a copy of the GNU General Public License version
    -# 2 along with this work; if not, write to the Free Software Foundation,
    -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    -#
    -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    -# or visit www.oracle.com if you need additional information or have any
    -# questions.
    -#
    -# tzdb timezone descriptions (deprecated version)
    -#
    -# This file is in the public domain, so clarified as of
    -# 2009-05-17 by Arthur David Olson.
    -#
    -# From Paul Eggert (2021-09-20):
    -# This file is intended as a backward-compatibility aid for older programs.
    -# New programs should use zone1970.tab.  This file is like zone1970.tab (see
    -# zone1970.tab's comments), but with the following additional restrictions:
    -#
    -# 1.  This file contains only ASCII characters.
    -# 2.  The first data column contains exactly one country code.
    -#
    -# Because of (2), each row stands for an area that is the intersection
    -# of a region identified by a country code and of a timezone where civil
    -# clocks have agreed since 1970; this is a narrower definition than
    -# that of zone1970.tab.
    -#
    -# Unlike zone1970.tab, a row's third column can be a Link from
    -# 'backward' instead of a Zone.
    -#
    -# This table is intended as an aid for users, to help them select timezones
    -# appropriate for their practical needs.  It is not intended to take or
    -# endorse any position on legal or territorial claims.
    -#
    -#country-
    -#code	coordinates	TZ			comments
    -AD	+4230+00131	Europe/Andorra
    -AE	+2518+05518	Asia/Dubai
    -AF	+3431+06912	Asia/Kabul
    -AG	+1703-06148	America/Antigua
    -AI	+1812-06304	America/Anguilla
    -AL	+4120+01950	Europe/Tirane
    -AM	+4011+04430	Asia/Yerevan
    -AO	-0848+01314	Africa/Luanda
    -AQ	-7750+16636	Antarctica/McMurdo	New Zealand time - McMurdo, South Pole
    -AQ	-6617+11031	Antarctica/Casey	Casey
    -AQ	-6835+07758	Antarctica/Davis	Davis
    -AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville
    -AQ	-6736+06253	Antarctica/Mawson	Mawson
    -AQ	-6448-06406	Antarctica/Palmer	Palmer
    -AQ	-6734-06808	Antarctica/Rothera	Rothera
    -AQ	-690022+0393524	Antarctica/Syowa	Syowa
    -AQ	-720041+0023206	Antarctica/Troll	Troll
    -AQ	-7824+10654	Antarctica/Vostok	Vostok
    -AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
    -AR	-3124-06411	America/Argentina/Cordoba	Argentina (most areas: CB, CC, CN, ER, FM, MN, SE, SF)
    -AR	-2447-06525	America/Argentina/Salta	Salta (SA, LP, NQ, RN)
    -AR	-2411-06518	America/Argentina/Jujuy	Jujuy (JY)
    -AR	-2649-06513	America/Argentina/Tucuman	Tucuman (TM)
    -AR	-2828-06547	America/Argentina/Catamarca	Catamarca (CT), Chubut (CH)
    -AR	-2926-06651	America/Argentina/La_Rioja	La Rioja (LR)
    -AR	-3132-06831	America/Argentina/San_Juan	San Juan (SJ)
    -AR	-3253-06849	America/Argentina/Mendoza	Mendoza (MZ)
    -AR	-3319-06621	America/Argentina/San_Luis	San Luis (SL)
    -AR	-5138-06913	America/Argentina/Rio_Gallegos	Santa Cruz (SC)
    -AR	-5448-06818	America/Argentina/Ushuaia	Tierra del Fuego (TF)
    -AS	-1416-17042	Pacific/Pago_Pago
    -AT	+4813+01620	Europe/Vienna
    -AU	-3133+15905	Australia/Lord_Howe	Lord Howe Island
    -AU	-5430+15857	Antarctica/Macquarie	Macquarie Island
    -AU	-4253+14719	Australia/Hobart	Tasmania
    -AU	-3749+14458	Australia/Melbourne	Victoria
    -AU	-3352+15113	Australia/Sydney	New South Wales (most areas)
    -AU	-3157+14127	Australia/Broken_Hill	New South Wales (Yancowinna)
    -AU	-2728+15302	Australia/Brisbane	Queensland (most areas)
    -AU	-2016+14900	Australia/Lindeman	Queensland (Whitsunday Islands)
    -AU	-3455+13835	Australia/Adelaide	South Australia
    -AU	-1228+13050	Australia/Darwin	Northern Territory
    -AU	-3157+11551	Australia/Perth	Western Australia (most areas)
    -AU	-3143+12852	Australia/Eucla	Western Australia (Eucla)
    -AW	+1230-06958	America/Aruba
    -AX	+6006+01957	Europe/Mariehamn
    -AZ	+4023+04951	Asia/Baku
    -BA	+4352+01825	Europe/Sarajevo
    -BB	+1306-05937	America/Barbados
    -BD	+2343+09025	Asia/Dhaka
    -BE	+5050+00420	Europe/Brussels
    -BF	+1222-00131	Africa/Ouagadougou
    -BG	+4241+02319	Europe/Sofia
    -BH	+2623+05035	Asia/Bahrain
    -BI	-0323+02922	Africa/Bujumbura
    -BJ	+0629+00237	Africa/Porto-Novo
    -BL	+1753-06251	America/St_Barthelemy
    -BM	+3217-06446	Atlantic/Bermuda
    -BN	+0456+11455	Asia/Brunei
    -BO	-1630-06809	America/La_Paz
    -BQ	+120903-0681636	America/Kralendijk
    -BR	-0351-03225	America/Noronha	Atlantic islands
    -BR	-0127-04829	America/Belem	Para (east), Amapa
    -BR	-0343-03830	America/Fortaleza	Brazil (northeast: MA, PI, CE, RN, PB)
    -BR	-0803-03454	America/Recife	Pernambuco
    -BR	-0712-04812	America/Araguaina	Tocantins
    -BR	-0940-03543	America/Maceio	Alagoas, Sergipe
    -BR	-1259-03831	America/Bahia	Bahia
    -BR	-2332-04637	America/Sao_Paulo	Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)
    -BR	-2027-05437	America/Campo_Grande	Mato Grosso do Sul
    -BR	-1535-05605	America/Cuiaba	Mato Grosso
    -BR	-0226-05452	America/Santarem	Para (west)
    -BR	-0846-06354	America/Porto_Velho	Rondonia
    -BR	+0249-06040	America/Boa_Vista	Roraima
    -BR	-0308-06001	America/Manaus	Amazonas (east)
    -BR	-0640-06952	America/Eirunepe	Amazonas (west)
    -BR	-0958-06748	America/Rio_Branco	Acre
    -BS	+2505-07721	America/Nassau
    -BT	+2728+08939	Asia/Thimphu
    -BW	-2439+02555	Africa/Gaborone
    -BY	+5354+02734	Europe/Minsk
    -BZ	+1730-08812	America/Belize
    -CA	+4734-05243	America/St_Johns	Newfoundland, Labrador (SE)
    -CA	+4439-06336	America/Halifax	Atlantic - NS (most areas), PE
    -CA	+4612-05957	America/Glace_Bay	Atlantic - NS (Cape Breton)
    -CA	+4606-06447	America/Moncton	Atlantic - New Brunswick
    -CA	+5320-06025	America/Goose_Bay	Atlantic - Labrador (most areas)
    -CA	+5125-05707	America/Blanc-Sablon	AST - QC (Lower North Shore)
    -CA	+4339-07923	America/Toronto	Eastern - ON & QC (most areas)
    -CA	+6344-06828	America/Iqaluit	Eastern - NU (most areas)
    -CA	+484531-0913718	America/Atikokan	EST - ON (Atikokan), NU (Coral H)
    -CA	+4953-09709	America/Winnipeg	Central - ON (west), Manitoba
    -CA	+744144-0944945	America/Resolute	Central - NU (Resolute)
    -CA	+624900-0920459	America/Rankin_Inlet	Central - NU (central)
    -CA	+5024-10439	America/Regina	CST - SK (most areas)
    -CA	+5017-10750	America/Swift_Current	CST - SK (midwest)
    -CA	+5333-11328	America/Edmonton	Mountain - AB, BC(E), NT(E), SK(W)
    -CA	+690650-1050310	America/Cambridge_Bay	Mountain - NU (west)
    -CA	+682059-1334300	America/Inuvik	Mountain - NT (west)
    -CA	+4906-11631	America/Creston	MST - BC (Creston)
    -CA	+5546-12014	America/Dawson_Creek	MST - BC (Dawson Cr, Ft St John)
    -CA	+5848-12242	America/Fort_Nelson	MST - BC (Ft Nelson)
    -CA	+6043-13503	America/Whitehorse	MST - Yukon (east)
    -CA	+6404-13925	America/Dawson	MST - Yukon (west)
    -CA	+4916-12307	America/Vancouver	Pacific - BC (most areas)
    -CC	-1210+09655	Indian/Cocos
    -CD	-0418+01518	Africa/Kinshasa	Dem. Rep. of Congo (west)
    -CD	-1140+02728	Africa/Lubumbashi	Dem. Rep. of Congo (east)
    -CF	+0422+01835	Africa/Bangui
    -CG	-0416+01517	Africa/Brazzaville
    -CH	+4723+00832	Europe/Zurich
    -CI	+0519-00402	Africa/Abidjan
    -CK	-2114-15946	Pacific/Rarotonga
    -CL	-3327-07040	America/Santiago	most of Chile
    -CL	-5309-07055	America/Punta_Arenas	Region of Magallanes
    -CL	-2709-10926	Pacific/Easter	Easter Island
    -CM	+0403+00942	Africa/Douala
    -CN	+3114+12128	Asia/Shanghai	Beijing Time
    -CN	+4348+08735	Asia/Urumqi	Xinjiang Time
    -CO	+0436-07405	America/Bogota
    -CR	+0956-08405	America/Costa_Rica
    -CU	+2308-08222	America/Havana
    -CV	+1455-02331	Atlantic/Cape_Verde
    -CW	+1211-06900	America/Curacao
    -CX	-1025+10543	Indian/Christmas
    -CY	+3510+03322	Asia/Nicosia	most of Cyprus
    -CY	+3507+03357	Asia/Famagusta	Northern Cyprus
    -CZ	+5005+01426	Europe/Prague
    -DE	+5230+01322	Europe/Berlin	most of Germany
    -DE	+4742+00841	Europe/Busingen	Busingen
    -DJ	+1136+04309	Africa/Djibouti
    -DK	+5540+01235	Europe/Copenhagen
    -DM	+1518-06124	America/Dominica
    -DO	+1828-06954	America/Santo_Domingo
    -DZ	+3647+00303	Africa/Algiers
    -EC	-0210-07950	America/Guayaquil	Ecuador (mainland)
    -EC	-0054-08936	Pacific/Galapagos	Galapagos Islands
    -EE	+5925+02445	Europe/Tallinn
    -EG	+3003+03115	Africa/Cairo
    -EH	+2709-01312	Africa/El_Aaiun
    -ER	+1520+03853	Africa/Asmara
    -ES	+4024-00341	Europe/Madrid	Spain (mainland)
    -ES	+3553-00519	Africa/Ceuta	Ceuta, Melilla
    -ES	+2806-01524	Atlantic/Canary	Canary Islands
    -ET	+0902+03842	Africa/Addis_Ababa
    -FI	+6010+02458	Europe/Helsinki
    -FJ	-1808+17825	Pacific/Fiji
    -FK	-5142-05751	Atlantic/Stanley
    -FM	+0725+15147	Pacific/Chuuk	Chuuk/Truk, Yap
    -FM	+0658+15813	Pacific/Pohnpei	Pohnpei/Ponape
    -FM	+0519+16259	Pacific/Kosrae	Kosrae
    -FO	+6201-00646	Atlantic/Faroe
    -FR	+4852+00220	Europe/Paris
    -GA	+0023+00927	Africa/Libreville
    -GB	+513030-0000731	Europe/London
    -GD	+1203-06145	America/Grenada
    -GE	+4143+04449	Asia/Tbilisi
    -GF	+0456-05220	America/Cayenne
    -GG	+492717-0023210	Europe/Guernsey
    -GH	+0533-00013	Africa/Accra
    -GI	+3608-00521	Europe/Gibraltar
    -GL	+6411-05144	America/Nuuk	most of Greenland
    -GL	+7646-01840	America/Danmarkshavn	National Park (east coast)
    -GL	+7029-02158	America/Scoresbysund	Scoresbysund/Ittoqqortoormiit
    -GL	+7634-06847	America/Thule	Thule/Pituffik
    -GM	+1328-01639	Africa/Banjul
    -GN	+0931-01343	Africa/Conakry
    -GP	+1614-06132	America/Guadeloupe
    -GQ	+0345+00847	Africa/Malabo
    -GR	+3758+02343	Europe/Athens
    -GS	-5416-03632	Atlantic/South_Georgia
    -GT	+1438-09031	America/Guatemala
    -GU	+1328+14445	Pacific/Guam
    -GW	+1151-01535	Africa/Bissau
    -GY	+0648-05810	America/Guyana
    -HK	+2217+11409	Asia/Hong_Kong
    -HN	+1406-08713	America/Tegucigalpa
    -HR	+4548+01558	Europe/Zagreb
    -HT	+1832-07220	America/Port-au-Prince
    -HU	+4730+01905	Europe/Budapest
    -ID	-0610+10648	Asia/Jakarta	Java, Sumatra
    -ID	-0002+10920	Asia/Pontianak	Borneo (west, central)
    -ID	-0507+11924	Asia/Makassar	Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
    -ID	-0232+14042	Asia/Jayapura	New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
    -IE	+5320-00615	Europe/Dublin
    -IL	+314650+0351326	Asia/Jerusalem
    -IM	+5409-00428	Europe/Isle_of_Man
    -IN	+2232+08822	Asia/Kolkata
    -IO	-0720+07225	Indian/Chagos
    -IQ	+3321+04425	Asia/Baghdad
    -IR	+3540+05126	Asia/Tehran
    -IS	+6409-02151	Atlantic/Reykjavik
    -IT	+4154+01229	Europe/Rome
    -JE	+491101-0020624	Europe/Jersey
    -JM	+175805-0764736	America/Jamaica
    -JO	+3157+03556	Asia/Amman
    -JP	+353916+1394441	Asia/Tokyo
    -KE	-0117+03649	Africa/Nairobi
    -KG	+4254+07436	Asia/Bishkek
    -KH	+1133+10455	Asia/Phnom_Penh
    -KI	+0125+17300	Pacific/Tarawa	Gilbert Islands
    -KI	-0247-17143	Pacific/Kanton	Phoenix Islands
    -KI	+0152-15720	Pacific/Kiritimati	Line Islands
    -KM	-1141+04316	Indian/Comoro
    -KN	+1718-06243	America/St_Kitts
    -KP	+3901+12545	Asia/Pyongyang
    -KR	+3733+12658	Asia/Seoul
    -KW	+2920+04759	Asia/Kuwait
    -KY	+1918-08123	America/Cayman
    -KZ	+4315+07657	Asia/Almaty	most of Kazakhstan
    -KZ	+4448+06528	Asia/Qyzylorda	Qyzylorda/Kyzylorda/Kzyl-Orda
    -KZ	+5312+06337	Asia/Qostanay	Qostanay/Kostanay/Kustanay
    -KZ	+5017+05710	Asia/Aqtobe	Aqtobe/Aktobe
    -KZ	+4431+05016	Asia/Aqtau	Mangghystau/Mankistau
    -KZ	+4707+05156	Asia/Atyrau	Atyrau/Atirau/Gur'yev
    -KZ	+5113+05121	Asia/Oral	West Kazakhstan
    -LA	+1758+10236	Asia/Vientiane
    -LB	+3353+03530	Asia/Beirut
    -LC	+1401-06100	America/St_Lucia
    -LI	+4709+00931	Europe/Vaduz
    -LK	+0656+07951	Asia/Colombo
    -LR	+0618-01047	Africa/Monrovia
    -LS	-2928+02730	Africa/Maseru
    -LT	+5441+02519	Europe/Vilnius
    -LU	+4936+00609	Europe/Luxembourg
    -LV	+5657+02406	Europe/Riga
    -LY	+3254+01311	Africa/Tripoli
    -MA	+3339-00735	Africa/Casablanca
    -MC	+4342+00723	Europe/Monaco
    -MD	+4700+02850	Europe/Chisinau
    -ME	+4226+01916	Europe/Podgorica
    -MF	+1804-06305	America/Marigot
    -MG	-1855+04731	Indian/Antananarivo
    -MH	+0709+17112	Pacific/Majuro	most of Marshall Islands
    -MH	+0905+16720	Pacific/Kwajalein	Kwajalein
    -MK	+4159+02126	Europe/Skopje
    -ML	+1239-00800	Africa/Bamako
    -MM	+1647+09610	Asia/Yangon
    -MN	+4755+10653	Asia/Ulaanbaatar	most of Mongolia
    -MN	+4801+09139	Asia/Hovd	Bayan-Olgii, Hovd, Uvs
    -MO	+221150+1133230	Asia/Macau
    -MP	+1512+14545	Pacific/Saipan
    -MQ	+1436-06105	America/Martinique
    -MR	+1806-01557	Africa/Nouakchott
    -MS	+1643-06213	America/Montserrat
    -MT	+3554+01431	Europe/Malta
    -MU	-2010+05730	Indian/Mauritius
    -MV	+0410+07330	Indian/Maldives
    -MW	-1547+03500	Africa/Blantyre
    -MX	+1924-09909	America/Mexico_City	Central Mexico
    -MX	+2105-08646	America/Cancun	Quintana Roo
    -MX	+2058-08937	America/Merida	Campeche, Yucatan
    -MX	+2540-10019	America/Monterrey	Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas)
    -MX	+2550-09730	America/Matamoros	Coahuila, Nuevo Leon, Tamaulipas (US border)
    -MX	+2838-10605	America/Chihuahua	Chihuahua (most areas)
    -MX	+3144-10629	America/Ciudad_Juarez	Chihuahua (US border - west)
    -MX	+2934-10425	America/Ojinaga	Chihuahua (US border - east)
    -MX	+2313-10625	America/Mazatlan	Baja California Sur, Nayarit (most areas), Sinaloa
    -MX	+2048-10515	America/Bahia_Banderas	Bahia de Banderas
    -MX	+2904-11058	America/Hermosillo	Sonora
    -MX	+3232-11701	America/Tijuana	Baja California
    -MY	+0310+10142	Asia/Kuala_Lumpur	Malaysia (peninsula)
    -MY	+0133+11020	Asia/Kuching	Sabah, Sarawak
    -MZ	-2558+03235	Africa/Maputo
    -NA	-2234+01706	Africa/Windhoek
    -NC	-2216+16627	Pacific/Noumea
    -NE	+1331+00207	Africa/Niamey
    -NF	-2903+16758	Pacific/Norfolk
    -NG	+0627+00324	Africa/Lagos
    -NI	+1209-08617	America/Managua
    -NL	+5222+00454	Europe/Amsterdam
    -NO	+5955+01045	Europe/Oslo
    -NP	+2743+08519	Asia/Kathmandu
    -NR	-0031+16655	Pacific/Nauru
    -NU	-1901-16955	Pacific/Niue
    -NZ	-3652+17446	Pacific/Auckland	most of New Zealand
    -NZ	-4357-17633	Pacific/Chatham	Chatham Islands
    -OM	+2336+05835	Asia/Muscat
    -PA	+0858-07932	America/Panama
    -PE	-1203-07703	America/Lima
    -PF	-1732-14934	Pacific/Tahiti	Society Islands
    -PF	-0900-13930	Pacific/Marquesas	Marquesas Islands
    -PF	-2308-13457	Pacific/Gambier	Gambier Islands
    -PG	-0930+14710	Pacific/Port_Moresby	most of Papua New Guinea
    -PG	-0613+15534	Pacific/Bougainville	Bougainville
    -PH	+1435+12100	Asia/Manila
    -PK	+2452+06703	Asia/Karachi
    -PL	+5215+02100	Europe/Warsaw
    -PM	+4703-05620	America/Miquelon
    -PN	-2504-13005	Pacific/Pitcairn
    -PR	+182806-0660622	America/Puerto_Rico
    -PS	+3130+03428	Asia/Gaza	Gaza Strip
    -PS	+313200+0350542	Asia/Hebron	West Bank
    -PT	+3843-00908	Europe/Lisbon	Portugal (mainland)
    -PT	+3238-01654	Atlantic/Madeira	Madeira Islands
    -PT	+3744-02540	Atlantic/Azores	Azores
    -PW	+0720+13429	Pacific/Palau
    -PY	-2516-05740	America/Asuncion
    -QA	+2517+05132	Asia/Qatar
    -RE	-2052+05528	Indian/Reunion
    -RO	+4426+02606	Europe/Bucharest
    -RS	+4450+02030	Europe/Belgrade
    -RU	+5443+02030	Europe/Kaliningrad	MSK-01 - Kaliningrad
    -RU	+554521+0373704	Europe/Moscow	MSK+00 - Moscow area
    -# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
    -# Put it in RU section and list as UA.  See "territorial claims" above.
    -# Programs should use zone1970.tab instead; see above.
    -UA	+4457+03406	Europe/Simferopol	Crimea
    -RU	+5836+04939	Europe/Kirov	MSK+00 - Kirov
    -RU	+4844+04425	Europe/Volgograd	MSK+00 - Volgograd
    -RU	+4621+04803	Europe/Astrakhan	MSK+01 - Astrakhan
    -RU	+5134+04602	Europe/Saratov	MSK+01 - Saratov
    -RU	+5420+04824	Europe/Ulyanovsk	MSK+01 - Ulyanovsk
    -RU	+5312+05009	Europe/Samara	MSK+01 - Samara, Udmurtia
    -RU	+5651+06036	Asia/Yekaterinburg	MSK+02 - Urals
    -RU	+5500+07324	Asia/Omsk	MSK+03 - Omsk
    -RU	+5502+08255	Asia/Novosibirsk	MSK+04 - Novosibirsk
    -RU	+5322+08345	Asia/Barnaul	MSK+04 - Altai
    -RU	+5630+08458	Asia/Tomsk	MSK+04 - Tomsk
    -RU	+5345+08707	Asia/Novokuznetsk	MSK+04 - Kemerovo
    -RU	+5601+09250	Asia/Krasnoyarsk	MSK+04 - Krasnoyarsk area
    -RU	+5216+10420	Asia/Irkutsk	MSK+05 - Irkutsk, Buryatia
    -RU	+5203+11328	Asia/Chita	MSK+06 - Zabaykalsky
    -RU	+6200+12940	Asia/Yakutsk	MSK+06 - Lena River
    -RU	+623923+1353314	Asia/Khandyga	MSK+06 - Tomponsky, Ust-Maysky
    -RU	+4310+13156	Asia/Vladivostok	MSK+07 - Amur River
    -RU	+643337+1431336	Asia/Ust-Nera	MSK+07 - Oymyakonsky
    -RU	+5934+15048	Asia/Magadan	MSK+08 - Magadan
    -RU	+4658+14242	Asia/Sakhalin	MSK+08 - Sakhalin Island
    -RU	+6728+15343	Asia/Srednekolymsk	MSK+08 - Sakha (E), N Kuril Is
    -RU	+5301+15839	Asia/Kamchatka	MSK+09 - Kamchatka
    -RU	+6445+17729	Asia/Anadyr	MSK+09 - Bering Sea
    -RW	-0157+03004	Africa/Kigali
    -SA	+2438+04643	Asia/Riyadh
    -SB	-0932+16012	Pacific/Guadalcanal
    -SC	-0440+05528	Indian/Mahe
    -SD	+1536+03232	Africa/Khartoum
    -SE	+5920+01803	Europe/Stockholm
    -SG	+0117+10351	Asia/Singapore
    -SH	-1555-00542	Atlantic/St_Helena
    -SI	+4603+01431	Europe/Ljubljana
    -SJ	+7800+01600	Arctic/Longyearbyen
    -SK	+4809+01707	Europe/Bratislava
    -SL	+0830-01315	Africa/Freetown
    -SM	+4355+01228	Europe/San_Marino
    -SN	+1440-01726	Africa/Dakar
    -SO	+0204+04522	Africa/Mogadishu
    -SR	+0550-05510	America/Paramaribo
    -SS	+0451+03137	Africa/Juba
    -ST	+0020+00644	Africa/Sao_Tome
    -SV	+1342-08912	America/El_Salvador
    -SX	+180305-0630250	America/Lower_Princes
    -SY	+3330+03618	Asia/Damascus
    -SZ	-2618+03106	Africa/Mbabane
    -TC	+2128-07108	America/Grand_Turk
    -TD	+1207+01503	Africa/Ndjamena
    -TF	-492110+0701303	Indian/Kerguelen
    -TG	+0608+00113	Africa/Lome
    -TH	+1345+10031	Asia/Bangkok
    -TJ	+3835+06848	Asia/Dushanbe
    -TK	-0922-17114	Pacific/Fakaofo
    -TL	-0833+12535	Asia/Dili
    -TM	+3757+05823	Asia/Ashgabat
    -TN	+3648+01011	Africa/Tunis
    -TO	-210800-1751200	Pacific/Tongatapu
    -TR	+4101+02858	Europe/Istanbul
    -TT	+1039-06131	America/Port_of_Spain
    -TV	-0831+17913	Pacific/Funafuti
    -TW	+2503+12130	Asia/Taipei
    -TZ	-0648+03917	Africa/Dar_es_Salaam
    -UA	+5026+03031	Europe/Kyiv	most of Ukraine
    -UG	+0019+03225	Africa/Kampala
    -UM	+2813-17722	Pacific/Midway	Midway Islands
    -UM	+1917+16637	Pacific/Wake	Wake Island
    -US	+404251-0740023	America/New_York	Eastern (most areas)
    -US	+421953-0830245	America/Detroit	Eastern - MI (most areas)
    -US	+381515-0854534	America/Kentucky/Louisville	Eastern - KY (Louisville area)
    -US	+364947-0845057	America/Kentucky/Monticello	Eastern - KY (Wayne)
    -US	+394606-0860929	America/Indiana/Indianapolis	Eastern - IN (most areas)
    -US	+384038-0873143	America/Indiana/Vincennes	Eastern - IN (Da, Du, K, Mn)
    -US	+410305-0863611	America/Indiana/Winamac	Eastern - IN (Pulaski)
    -US	+382232-0862041	America/Indiana/Marengo	Eastern - IN (Crawford)
    -US	+382931-0871643	America/Indiana/Petersburg	Eastern - IN (Pike)
    -US	+384452-0850402	America/Indiana/Vevay	Eastern - IN (Switzerland)
    -US	+415100-0873900	America/Chicago	Central (most areas)
    -US	+375711-0864541	America/Indiana/Tell_City	Central - IN (Perry)
    -US	+411745-0863730	America/Indiana/Knox	Central - IN (Starke)
    -US	+450628-0873651	America/Menominee	Central - MI (Wisconsin border)
    -US	+470659-1011757	America/North_Dakota/Center	Central - ND (Oliver)
    -US	+465042-1012439	America/North_Dakota/New_Salem	Central - ND (Morton rural)
    -US	+471551-1014640	America/North_Dakota/Beulah	Central - ND (Mercer)
    -US	+394421-1045903	America/Denver	Mountain (most areas)
    -US	+433649-1161209	America/Boise	Mountain - ID (south), OR (east)
    -US	+332654-1120424	America/Phoenix	MST - AZ (except Navajo)
    -US	+340308-1181434	America/Los_Angeles	Pacific
    -US	+611305-1495401	America/Anchorage	Alaska (most areas)
    -US	+581807-1342511	America/Juneau	Alaska - Juneau area
    -US	+571035-1351807	America/Sitka	Alaska - Sitka area
    -US	+550737-1313435	America/Metlakatla	Alaska - Annette Island
    -US	+593249-1394338	America/Yakutat	Alaska - Yakutat
    -US	+643004-1652423	America/Nome	Alaska (west)
    -US	+515248-1763929	America/Adak	Alaska - western Aleutians
    -US	+211825-1575130	Pacific/Honolulu	Hawaii
    -UY	-345433-0561245	America/Montevideo
    -UZ	+3940+06648	Asia/Samarkand	Uzbekistan (west)
    -UZ	+4120+06918	Asia/Tashkent	Uzbekistan (east)
    -VA	+415408+0122711	Europe/Vatican
    -VC	+1309-06114	America/St_Vincent
    -VE	+1030-06656	America/Caracas
    -VG	+1827-06437	America/Tortola
    -VI	+1821-06456	America/St_Thomas
    -VN	+1045+10640	Asia/Ho_Chi_Minh
    -VU	-1740+16825	Pacific/Efate
    -WF	-1318-17610	Pacific/Wallis
    -WS	-1350-17144	Pacific/Apia
    -YE	+1245+04512	Asia/Aden
    -YT	-1247+04514	Indian/Mayotte
    -ZA	-2615+02800	Africa/Johannesburg
    -ZM	-1525+02817	Africa/Lusaka
    -ZW	-1750+03103	Africa/Harare
    diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md
    index 01f7b3f7e77..a048d2a6dcf 100644
    --- a/src/java.base/share/man/java.md
    +++ b/src/java.base/share/man/java.md
    @@ -1311,7 +1311,7 @@ These `java` options control the runtime behavior of the Java HotSpot VM.
     `-XX:+PreserveFramePointer`
     :   Selects between using the RBP register as a general purpose register
         (`-XX:-PreserveFramePointer`) and using the RBP register to hold the frame
    -    pointer of the currently executing method (`-XX:+PreserveFramePointer` . If
    +    pointer of the currently executing method (`-XX:+PreserveFramePointer`). If
         the frame pointer is available, then external profiling tools (for example,
         Linux perf) can construct more accurate stack traces.
     
    diff --git a/src/java.base/share/man/keytool.md b/src/java.base/share/man/keytool.md
    index 22b2877a3e7..8484ec6b5b3 100644
    --- a/src/java.base/share/man/keytool.md
    +++ b/src/java.base/share/man/keytool.md
    @@ -662,7 +662,7 @@ perform.
     
         -   {`-noprompt`}: Do not prompt
     
    -    -   {`-addprovider` *name* \[`-providerarg` *arg*\]: Add security provider
    +    -   {`-addprovider` *name* \[`-providerarg` *arg*\]}: Add security provider
             by name (such as SunPKCS11) with an optional configure argument.
     
         -   {`-providerclass` *class* \[`-providerarg` *arg*\]}: Add security
    @@ -1617,7 +1617,7 @@ name information, the keystore password, and the private key password.
     The rest of the examples assume that you responded to the prompts with values
     equal to those specified in the first `-genkeypair` command. For example, a
     distinguished name of
    -`cn=`*myname*`, ou=`*mygroup*`, o=`*mycompany*`, c=`*mycountry*).
    +`cn=`*myname*`, ou=`*mygroup*`, o=`*mycompany*`, c=`*mycountry*.
     
     ## Requesting a Signed Certificate from a CA
     
    @@ -1914,7 +1914,7 @@ Keystore implementation
         The `keytool` command works on any file-based keystore implementation. It
         treats the keystore location that is passed to it at the command line as a
         file name and converts it to a `FileInputStream`, from which it loads the
    -    keystore information.)The `jarsigner` commands can read a keystore from any
    +    keystore information. The `jarsigner` commands can read a keystore from any
         location that can be specified with a URL.
     
         For `keytool` and `jarsigner`, you can specify a keystore type at the
    diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c
    index 506b33aae96..5a3a5cd088a 100644
    --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c
    +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c
    @@ -558,7 +558,9 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
             return -1;
         }
         offset = copystrings(buf, 0, &c->argv[0]);
    -    offset = copystrings(buf, offset, &c->envv[0]);
    +    if (c->envv != NULL) {
    +        offset = copystrings(buf, offset, &c->envv[0]);
    +    }
         if (c->pdir != NULL) {
             if (sp.dirlen > 0) {
                 memcpy(buf+offset, c->pdir, sp.dirlen);
    diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
    index 7e138a5cc11..1e4b6a05ce1 100644
    --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
    +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
    @@ -78,7 +78,7 @@ public void init() throws IOException {
                 connector.run();
                 if (ioe instanceof ClosedByInterruptException) {
                     ioe = null;
    -                Thread connThread = new Thread(connector) {
    +                Thread connThread = new Thread(connector, "LoopbackConnector") {
                         @Override
                         public void interrupt() {}
                     };
    diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java
    index 79c86de16c6..19d77115025 100644
    --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java
    +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 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
    @@ -621,7 +621,6 @@ public void installComponents(JFileChooser fc) {
     
             fc.add(interior, BorderLayout.CENTER);
     
    -        @SuppressWarnings("serial") // anonymous class
             JPanel comboBoxPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,
                                                              0, 0) {
                 public void layoutContainer(Container target) {
    @@ -733,7 +732,6 @@ public void layoutContainer(Container target) {
             if (currentDirectory != null) {
                 curDirName = currentDirectory.getPath();
             }
    -        @SuppressWarnings("serial") // anonymous class
             JLabel tmp = new JLabel(curDirName) {
                 public Dimension getMaximumSize() {
                     Dimension d = super.getMaximumSize();
    @@ -748,7 +746,6 @@ public Dimension getMaximumSize() {
             interior.add(pathFieldPanel);
     
             // add the fileName field
    -        @SuppressWarnings("serial") // anonymous class
             JTextField tmp2 = new JTextField() {
                 public Dimension getMaximumSize() {
                     Dimension d = super.getMaximumSize();
    diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java
    index ba1927bb948..ad6b226dd70 100644
    --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java
    +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -25,7 +25,9 @@
     package javax.swing.plaf.synth;
     
     import sun.swing.DefaultLookup;
    +
     import javax.swing.JComponent;
    +import javax.swing.UIManager;
     import javax.swing.plaf.ComponentUI;
     
     /**
    @@ -35,6 +37,12 @@
      */
     class SynthDefaultLookup extends DefaultLookup {
         public Object getDefault(JComponent c, ComponentUI ui, String key) {
    +        if (ui instanceof SynthOptionPaneUI) {
    +            Object value = super.getDefault(c, ui, key);
    +            if (value != null) {
    +                return value;
    +            }
    +        }
             if (!(ui instanceof SynthUI)) {
                 Object value = super.getDefault(c, ui, key);
                 return value;
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java
    index 79d6965e05f..42e684bfac7 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 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
    @@ -168,7 +168,6 @@ public boolean isReparentSupported() {
             return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false");
         }
     
    -    @SuppressWarnings("deprecation")
         public boolean isObscured() {
             Container container  = (target instanceof Container) ?
                 (Container)target : target.getParent();
    @@ -244,7 +243,6 @@ static final AWTEvent wrapInSequenced(AWTEvent event) {
         }
     
         // TODO: consider moving it to KeyboardFocusManagerPeerImpl
    -    @SuppressWarnings("deprecation")
         public final boolean requestFocus(Component lightweightChild, boolean temporary,
                                           boolean focusedWindowChangeAllowed, long time,
                                           FocusEvent.Cause cause)
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java
    index 98caf9f43cf..5c6fde2251c 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XFileDialogPeer.java
    @@ -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
    @@ -197,7 +197,6 @@ private void init(FileDialog target) {
             // After showing we should display 'user.dir' as current directory
             // if user didn't set directory programmatically
             pathField = new TextField(savedDir != null ? savedDir : userDir);
    -        @SuppressWarnings("serial") // Anonymous class
             Choice tmp = new Choice() {
                     public Dimension getPreferredSize() {
                         return new Dimension(PATH_CHOICE_WIDTH, pathField.getPreferredSize().height);
    @@ -778,7 +777,6 @@ public void dispose() {
         }
     
         // 03/02/2005 b5097243 Pressing 'ESC' on a file dlg does not dispose the dlg on Xtoolkit
    -    @SuppressWarnings("deprecation")
         public void setVisible(boolean b){
             if (fileDialog == null) {
                 init(target);
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XFramePeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XFramePeer.java
    index c7f3ba95bc1..acbe8639702 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XFramePeer.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XFramePeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 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
    @@ -137,7 +137,6 @@ void setupState(boolean onInit) {
             setExtendedState(state);
         }
     
    -    @SuppressWarnings("deprecation")
         public void setMenuBar(MenuBar mb) {
             // state_lock should always be the second after awt_lock
             XToolkit.awtLock();
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java
    index f4c46c2766d..321cb4fbf1e 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2017, 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
    @@ -83,7 +83,6 @@ public int fillPointWithCoords(Point point) {
             return 0;
         }
     
    -    @SuppressWarnings("deprecation")
         public boolean isWindowUnderMouse(Window w) {
             if (w == null) {
                 return false;
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
    index a37e82d2273..cda05e0a6c7 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 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
    @@ -214,7 +214,6 @@ protected String getWMName() {
         private static native String getLocalHostname();
         private static native int getJvmPID();
     
    -    @SuppressWarnings("deprecation")
         void postInit(XCreateWindowParams params) {
             super.postInit(params);
     
    diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java
    index 41fa0c3f048..7065e3db19b 100644
    --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java
    +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java
    @@ -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
    @@ -273,7 +273,6 @@ public void installComponents(JFileChooser fc) {
             fc.add(topPanel, BorderLayout.NORTH);
     
             // ComboBox Label
    -        @SuppressWarnings("serial") // anonymous class
             JLabel tmp1 = new JLabel(lookInLabelText, JLabel.TRAILING) {
                 public Dimension getPreferredSize() {
                     return getMinimumSize();
    @@ -295,7 +294,6 @@ public Dimension getMinimumSize() {
             topPanel.add(Box.createRigidArea(new Dimension(8,0)));
     
             // CurrentDir ComboBox
    -        @SuppressWarnings("serial") // anonymous class
             JComboBox tmp2 = new JComboBox() {
                 public Dimension getMinimumSize() {
                     Dimension d = super.getMinimumSize();
    @@ -477,7 +475,6 @@ public void propertyChange(PropertyChangeEvent e) {
             fileAndFilterPanel.add(Box.createRigidArea(vstrut8));
             fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel, BoxLayout.Y_AXIS));
     
    -        @SuppressWarnings("serial") // anonymous class
             JTextField tmp3 = new JTextField(35) {
                 public Dimension getMaximumSize() {
                     return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
    @@ -518,7 +515,6 @@ public void focusGained(FocusEvent e) {
             // buttons
             getButtonPanel().setLayout(new BoxLayout(getButtonPanel(), BoxLayout.Y_AXIS));
     
    -        @SuppressWarnings("serial") // anonymous class
             JButton tmp4 = new JButton(getApproveButtonText(fc)) {
                 public Dimension getMaximumSize() {
                     return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
    @@ -537,7 +533,6 @@ public Dimension getMaximumSize() {
             getButtonPanel().add(approveButton);
             getButtonPanel().add(Box.createRigidArea(vstrut4));
     
    -        @SuppressWarnings("serial") // anonymous class
             JButton tmp5 = new JButton(cancelButtonText) {
                 public Dimension getMaximumSize() {
                     return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ?
    @@ -974,7 +969,6 @@ protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser
             return new DirectoryComboBoxRenderer();
         }
     
    -    @SuppressWarnings("serial") // anonymous class
         private static JButton createToolButton(Action a, Icon defaultIcon, String toolTipText, String accessibleName) {
             final JButton result = new JButton(a);
     
    diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java
    index cd0987a9079..083563b4464 100644
    --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java
    +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2001, 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
    @@ -289,7 +289,6 @@ protected void assembleSystemMenu() {
             systemPopupMenu = new JPopupMenu();
             addSystemMenuItems(systemPopupMenu);
             enableActions();
    -        @SuppressWarnings("serial") // anonymous class
             JLabel tmp = new JLabel(frame.getFrameIcon()) {
                 protected void paintComponent(Graphics g) {
                     int x = 0;
    diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java
    index 930064d5981..a02bceae7fb 100644
    --- a/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java
    +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1996, 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
    @@ -94,7 +94,6 @@ protected void realShow() {
         }
     
         @Override
    -    @SuppressWarnings("deprecation")
         void hide() {
             Dialog dlg = (Dialog)target;
             if (dlg.getModalityType() != Dialog.ModalityType.MODELESS) {
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    index e28c0fe60f8..1131800f8ed 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 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
    @@ -30,16 +30,17 @@
     import java.util.Map;
     import java.util.Optional;
     import java.util.concurrent.ConcurrentHashMap;
    +import java.util.stream.Stream;
     
    -import com.sun.tools.javac.code.Symbol.*;
     import com.sun.tools.javac.main.Option;
    +import com.sun.tools.javac.tree.JCTree.*;
    +import com.sun.tools.javac.util.Assert;
     import com.sun.tools.javac.util.Context;
     import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
     import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
    -import com.sun.tools.javac.util.List;
     import com.sun.tools.javac.util.Log;
    +import com.sun.tools.javac.util.Names;
     import com.sun.tools.javac.util.Options;
    -import com.sun.tools.javac.util.Pair;
     
     /**
      * A class for handling -Xlint suboptions and @SuppressWarnings.
    @@ -49,8 +50,8 @@
      *  This code and its internal interfaces are subject to change or
      *  deletion without notice.
      */
    -public class Lint
    -{
    +public class Lint {
    +
         /** The context key for the root Lint object. */
         protected static final Context.Key lintKey = new Context.Key<>();
     
    @@ -63,26 +64,35 @@ public static Lint instance(Context context) {
         }
     
         /**
    -     * Returns the result of combining the values in this object with
    -     * the given annotation.
    +     * Obtain an instance with additional warning supression applied from any
    +     * @SuppressWarnings and/or @Deprecated annotations on the given symbol.
    +     *
    +     * 

    + * The returned instance will be different from this instance if and only if + * {@link #suppressionsFrom} returns a non-empty set. + * + * @param sym symbol + * @return lint instance with new warning suppressions applied, or this instance if none */ - public Lint augment(Attribute.Compound attr) { - return augmentor.augment(this, attr); + public Lint augment(Symbol sym) { + EnumSet suppressions = suppressionsFrom(sym); + if (!suppressions.isEmpty()) { + Lint lint = new Lint(this); + lint.values.removeAll(suppressions); + lint.suppressedValues.addAll(suppressions); + return lint; + } + return this; } - /** - * Returns the result of combining the values in this object with - * the metadata on the given symbol. + * Returns a new Lint that has the given LintCategorys enabled. + * @param lc one or more categories to be enabled */ - public Lint augment(Symbol sym) { - Lint l = augmentor.augment(this, sym.getDeclarationAttributes()); - if (sym.isDeprecated() && sym.isDeprecatableViaAnnotation()) { - if (l == this) - l = new Lint(this); - l.values.remove(LintCategory.DEPRECATION); - l.suppressedValues.add(LintCategory.DEPRECATION); - } + public Lint enable(LintCategory... lc) { + Lint l = new Lint(this); + l.values.addAll(Arrays.asList(lc)); + l.suppressedValues.removeAll(Arrays.asList(lc)); return l; } @@ -97,8 +107,13 @@ public Lint suppress(LintCategory... lc) { return l; } - private final AugmentVisitor augmentor; + private final Context context; + + // These are initialized lazily to avoid dependency loops + private Symtab syms; + private Names names; + // Invariant: it's never the case that a category is in both "values" and "suppressedValues" private final EnumSet values; private final EnumSet suppressedValues; @@ -114,10 +129,10 @@ protected Lint(Context context) { values = EnumSet.allOf(LintCategory.class); } else if (options.isSet(Option.XLINT_CUSTOM, "none")) { // if -Xlint:none is given, disable all categories by default - values = EnumSet.noneOf(LintCategory.class); + values = LintCategory.newEmptySet(); } else { // otherwise, enable on-by-default categories - values = EnumSet.noneOf(LintCategory.class); + values = LintCategory.newEmptySet(); Source source = Source.instance(context); if (source.compareTo(Source.JDK9) >= 0) { @@ -146,21 +161,23 @@ protected Lint(Context context) { } } - suppressedValues = EnumSet.noneOf(LintCategory.class); + suppressedValues = LintCategory.newEmptySet(); + this.context = context; context.put(lintKey, this); - augmentor = new AugmentVisitor(context); } protected Lint(Lint other) { - this.augmentor = other.augmentor; + this.context = other.context; + this.syms = other.syms; + this.names = other.names; this.values = other.values.clone(); this.suppressedValues = other.suppressedValues.clone(); } @Override public String toString() { - return "Lint:[values" + values + " suppressedValues" + suppressedValues + "]"; + return "Lint:[enable" + values + ",suppress" + suppressedValues + "]"; } /** @@ -373,6 +390,11 @@ public static Optional get(String option) { return Optional.ofNullable(map.get(option)); } + public static EnumSet newEmptySet() { + return EnumSet.noneOf(LintCategory.class); + } + + /** Get the string representing this category in @SuppressAnnotations and -Xlint options. */ public final String option; } @@ -404,82 +426,64 @@ public void logIfEnabled(Log log, DiagnosticPosition pos, LintWarning warning) { } } - protected static class AugmentVisitor implements Attribute.Visitor { - private final Context context; - private Symtab syms; - private Lint parent; - private Lint lint; - - AugmentVisitor(Context context) { - // to break an ugly sequence of initialization dependencies, - // we defer the initialization of syms until it is needed - this.context = context; - } - - Lint augment(Lint parent, Attribute.Compound attr) { - initSyms(); - this.parent = parent; - lint = null; - attr.accept(this); - return (lint == null ? parent : lint); - } - - Lint augment(Lint parent, List attrs) { - initSyms(); - this.parent = parent; - lint = null; - for (Attribute.Compound a: attrs) { - a.accept(this); - } - return (lint == null ? parent : lint); - } - - private void initSyms() { - if (syms == null) - syms = Symtab.instance(context); - } - - private void suppress(LintCategory lc) { - if (lint == null) - lint = new Lint(parent); - lint.suppressedValues.add(lc); - lint.values.remove(lc); - } - - public void visitConstant(Attribute.Constant value) { - if (value.type.tsym == syms.stringType.tsym) { - LintCategory.get((String)value.value) - .ifPresent(this::suppress); - } - } - - public void visitClass(Attribute.Class clazz) { - } - - // If we find a @SuppressWarnings annotation, then we continue - // walking the tree, in order to suppress the individual warnings - // specified in the @SuppressWarnings annotation. - public void visitCompound(Attribute.Compound compound) { - if (compound.type.tsym == syms.suppressWarningsType.tsym) { - for (List> v = compound.values; - v.nonEmpty(); v = v.tail) { - Pair value = v.head; - if (value.fst.name.toString().equals("value")) - value.snd.accept(this); - } + /** + * Obtain the set of recognized lint warning categories suppressed at the given symbol's declaration. + * + *

    + * This set can be non-empty only if the symbol is annotated with either + * @SuppressWarnings or @Deprecated. + * + * @param symbol symbol corresponding to a possibly-annotated declaration + * @return new warning suppressions applied to sym + */ + public EnumSet suppressionsFrom(Symbol symbol) { + EnumSet suppressions = suppressionsFrom(symbol.getDeclarationAttributes().stream()); + if (symbol.isDeprecated() && symbol.isDeprecatableViaAnnotation()) + suppressions.add(LintCategory.DEPRECATION); + return suppressions; + } - } - } + /** + * Retrieve the recognized lint categories suppressed by the given @SuppressWarnings annotation. + * + * @param annotation @SuppressWarnings annotation, or null + * @return set of lint categories, possibly empty but never null + */ + private EnumSet suppressionsFrom(JCAnnotation annotation) { + initializeIfNeeded(); + if (annotation == null) + return LintCategory.newEmptySet(); + Assert.check(annotation.attribute.type.tsym == syms.suppressWarningsType.tsym); + return suppressionsFrom(Stream.of(annotation).map(anno -> anno.attribute)); + } - public void visitArray(Attribute.Array array) { - for (Attribute value : array.values) - value.accept(this); - } + // Find the @SuppressWarnings annotation in the given stream and extract the recognized suppressions + private EnumSet suppressionsFrom(Stream attributes) { + initializeIfNeeded(); + EnumSet result = LintCategory.newEmptySet(); + attributes + .filter(attribute -> attribute.type.tsym == syms.suppressWarningsType.tsym) + .map(this::suppressionsFrom) + .forEach(result::addAll); + return result; + } - public void visitEnum(Attribute.Enum e) { + // Given a @SuppressWarnings annotation, extract the recognized suppressions + private EnumSet suppressionsFrom(Attribute.Compound suppressWarnings) { + EnumSet result = LintCategory.newEmptySet(); + Attribute.Array values = (Attribute.Array)suppressWarnings.member(names.value); + for (Attribute value : values.values) { + Optional.of((String)((Attribute.Constant)value).value) + .flatMap(LintCategory::get) + .ifPresent(result::add); } + return result; + } - public void visitError(Attribute.Error e) { + private void initializeIfNeeded() { + if (syms == null) { + syms = Symtab.instance(context); + names = Names.instance(context); } } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index a5b4186659b..a76dab2bb31 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -2945,11 +2945,19 @@ boolean potentiallyAmbiguousOverload(Type site, MethodSymbol msym1, MethodSymbol return potentiallyAmbiguous; } + // Apply special flag "-XDwarnOnAccessToMembers" which turns on just this particular warning for all types of access void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) { - if (warnOnAnyAccessToMembers || - (lint.isEnabled(LintCategory.SERIAL) && - !lint.isSuppressed(LintCategory.SERIAL) && - isLambda)) { + final Lint prevLint = setLint(warnOnAnyAccessToMembers ? lint.enable(LintCategory.SERIAL) : lint); + try { + if (warnOnAnyAccessToMembers || isLambda) + checkAccessFromSerializableElementInner(tree, isLambda); + } finally { + setLint(prevLint); + } + } + + private void checkAccessFromSerializableElementInner(final JCTree tree, boolean isLambda) { + if (lint.isEnabled(LintCategory.SERIAL)) { Symbol sym = TreeInfo.symbol(tree); if (!sym.kind.matches(KindSelector.VAL_MTH)) { return; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java index b9cab47d8ab..4896ecbe728 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -58,11 +58,12 @@ public enum CompileState { PROCESS(3), ATTR(4), FLOW(5), - TRANSTYPES(6), - TRANSPATTERNS(7), - LOWER(8), - UNLAMBDA(9), - GENERATE(10); + WARN(6), + TRANSTYPES(7), + TRANSPATTERNS(8), + LOWER(9), + UNLAMBDA(10), + GENERATE(11); CompileState(int value) { this.value = value; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 175cceeeb7f..b0b79104def 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -229,7 +229,6 @@ public void analyzeTree(Env env, TreeMaker make) { new AssignAnalyzer().analyzeTree(env, make); new FlowAnalyzer().analyzeTree(env, make); new CaptureAnalyzer().analyzeTree(env, make); - new ThisEscapeAnalyzer(names, syms, types, rs, log, lint).analyzeTree(env); } public void analyzeLambda(Env env, JCLambda that, TreeMaker make, boolean speculative) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index e1bf92a7f7b..77ddd5c6583 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -58,6 +58,7 @@ import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -140,8 +141,17 @@ *

  • We assume that native methods do not leak. *
  • We don't try to follow {@code super()} invocations; that's for the superclass analysis to handle. * + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -class ThisEscapeAnalyzer extends TreeScanner { +public class ThisEscapeAnalyzer extends TreeScanner { + + protected static final Context.Key contextKey = new Context.Key<>(); + +// Other singletons we utilize private final Names names; private final Symtab syms; @@ -211,15 +221,24 @@ class ThisEscapeAnalyzer extends TreeScanner { */ private RefSet refs; -// Constructor +// Access - ThisEscapeAnalyzer(Names names, Symtab syms, Types types, Resolve rs, Log log, Lint lint) { - this.names = names; - this.syms = syms; - this.types = types; - this.rs = rs; - this.log = log; - this.lint = lint; + public static ThisEscapeAnalyzer instance(Context context) { + ThisEscapeAnalyzer instance = context.get(contextKey); + if (instance == null) + instance = new ThisEscapeAnalyzer(context); + return instance; + } + + @SuppressWarnings("this-escape") + protected ThisEscapeAnalyzer(Context context) { + context.put(contextKey, this); + names = Names.instance(context); + log = Log.instance(context); + syms = Symtab.instance(context); + types = Types.instance(context); + rs = Resolve.instance(context); + lint = Lint.instance(context); } // @@ -227,6 +246,24 @@ class ThisEscapeAnalyzer extends TreeScanner { // public void analyzeTree(Env env) { + try { + doAnalyzeTree(env); + } finally { + attrEnv = null; + methodMap.clear(); + nonPublicOuters.clear(); + targetClass = null; + warningList.clear(); + methodClass = null; + callStack.clear(); + invocations.clear(); + pendingWarning = null; + depth = -1; + refs = null; + } + } + + private void doAnalyzeTree(Env env) { // Sanity check Assert.check(checkInvariants(false, false)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index a0b1ef27255..fe4d3d62f3b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -1168,7 +1168,7 @@ private Type erasure(Type t) { private Env env; private static final String statePreviousToFlowAssertMsg = - "The current compile state [%s] of class %s is previous to FLOW"; + "The current compile state [%s] of class %s is previous to WARN"; void translateClass(ClassSymbol c) { Type st = types.supertype(c.type); @@ -1189,7 +1189,7 @@ void translateClass(ClassSymbol c) { * 1) has no compile state being it the most outer class. * We accept this condition for inner classes. * - * 2) has a compile state which is previous to Flow state. + * 2) has a compile state which is previous to WARN state. */ boolean envHasCompState = compileStates.get(myEnv) != null; if (!envHasCompState && c.outermostClass() == c) { @@ -1197,7 +1197,7 @@ void translateClass(ClassSymbol c) { } if (envHasCompState && - CompileState.FLOW.isAfter(compileStates.get(myEnv))) { + CompileState.WARN.isAfter(compileStates.get(myEnv))) { Assert.error(String.format(statePreviousToFlowAssertMsg, compileStates.get(myEnv), myEnv.enclClass.sym)); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/WarningAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/WarningAnalyzer.java new file mode 100644 index 00000000000..00d1de386db --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/WarningAnalyzer.java @@ -0,0 +1,63 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.comp; + +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + +/** This pass checks for various things to warn about. + * It runs after attribution and flow analysis. + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class WarningAnalyzer { + + protected static final Context.Key contextKey = new Context.Key<>(); + + private final Log log; + private final ThisEscapeAnalyzer thisEscapeAnalyzer; + + public static WarningAnalyzer instance(Context context) { + WarningAnalyzer instance = context.get(contextKey); + if (instance == null) + instance = new WarningAnalyzer(context); + return instance; + } + + @SuppressWarnings("this-escape") + protected WarningAnalyzer(Context context) { + context.put(contextKey, this); + log = Log.instance(context); + thisEscapeAnalyzer = ThisEscapeAnalyzer.instance(context); + } + + public void analyzeTree(Env env) { + thisEscapeAnalyzer.analyzeTree(env); + } +} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java index 646db6a6bf3..4a5370f7a14 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -53,6 +53,7 @@ import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.main.Option; import com.sun.tools.javac.main.OptionHelper; import com.sun.tools.javac.main.OptionHelper.GrumpyHelper; @@ -90,10 +91,13 @@ public void setContext(Context context) { classLoaderClass = options.get("procloader"); // Detect Lint options, but use Options.isLintSet() to avoid initializing the Lint class - boolean warn = options.isLintSet("path"); + boolean warn = options.isLintSet(LintCategory.PATH.option); + boolean fileClashOption = options.isLintSet(LintCategory.OUTPUT_FILE_CLASH.option); locations.update(log, warn, FSInfo.instance(context)); + + // Only track file clashes if enabled synchronized (this) { - outputFilesWritten = options.isLintSet("output-file-clash") ? new HashSet<>() : null; + outputFilesWritten = fileClashOption ? new HashSet<>() : null; } // Setting this option is an indication that close() should defer actually closing diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 96cf4049533..05efcf7c041 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -306,6 +306,10 @@ else if (option.equals("class")) */ protected Flow flow; + /** The warning analyzer. + */ + protected WarningAnalyzer warningAnalyzer; + /** The modules visitor */ protected Modules modules; @@ -419,6 +423,7 @@ public JavaCompiler(Context context) { chk = Check.instance(context); gen = Gen.instance(context); flow = Flow.instance(context); + warningAnalyzer = WarningAnalyzer.instance(context); transTypes = TransTypes.instance(context); lower = Lower.instance(context); annotate = Annotate.instance(context); @@ -962,20 +967,20 @@ public void compile(Collection sourceFileObjects, if (!CompileState.ATTR.isAfter(shouldStopPolicyIfNoError)) { switch (compilePolicy) { case SIMPLE: - generate(desugar(flow(attribute(todo)))); + generate(desugar(warn(flow(attribute(todo))))); break; case BY_FILE: { Queue>> q = todo.groupByFile(); while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) { - generate(desugar(flow(attribute(q.remove())))); + generate(desugar(warn(flow(attribute(q.remove()))))); } } break; case BY_TODO: while (!todo.isEmpty()) - generate(desugar(flow(attribute(todo.remove())))); + generate(desugar(warn(flow(attribute(todo.remove()))))); break; default: @@ -1435,6 +1440,56 @@ protected void flow(Env env, Queue> results) { } } + /** + * Check for various things to warn about. + * + * @return the list of attributed parse trees + */ + public Queue> warn(Queue> envs) { + ListBuffer> results = new ListBuffer<>(); + for (Env env: envs) { + warn(env, results); + } + return stopIfError(CompileState.WARN, results); + } + + /** + * Check for various things to warn about in an attributed parse tree. + */ + public Queue> warn(Env env) { + ListBuffer> results = new ListBuffer<>(); + warn(env, results); + return stopIfError(CompileState.WARN, results); + } + + /** + * Check for various things to warn about in an attributed parse tree. + */ + protected void warn(Env env, Queue> results) { + if (compileStates.isDone(env, CompileState.WARN)) { + results.add(env); + return; + } + + if (shouldStop(CompileState.WARN)) + return; + + if (verboseCompilePolicy) + printNote("[warn " + env.enclClass.sym + "]"); + JavaFileObject prev = log.useSource( + env.enclClass.sym.sourcefile != null ? + env.enclClass.sym.sourcefile : + env.toplevel.sourcefile); + try { + warningAnalyzer.analyzeTree(env); + compileStates.put(env, CompileState.WARN); + results.add(env); + } + finally { + log.useSource(prev); + } + } + private TaskEvent newAnalyzeTaskEvent(Env env) { JCCompilationUnit toplevel = env.toplevel; ClassSymbol sym; @@ -1493,6 +1548,10 @@ protected void desugar(final Env env, Queue, return; } + // Ensure the file has reached the WARN state + if (!compileStates.isDone(env, CompileState.WARN)) + warn(env); + /** * Ensure that superclasses of C are desugared before C itself. This is * required for two reasons: (i) as erasure (TransTypes) destroys @@ -1576,8 +1635,8 @@ public void visitSwitchExpression(JCSwitchExpression tree) { ScanNested scanner = new ScanNested(); scanner.scan(env.tree); for (Env dep: scanner.dependencies) { - if (!compileStates.isDone(dep, CompileState.FLOW)) - desugaredEnvs.put(dep, desugar(flow(attribute(dep)))); + if (!compileStates.isDone(dep, CompileState.WARN)) + desugaredEnvs.put(dep, desugar(warn(flow(attribute(dep))))); } //We need to check for error another time as more classes might diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java index b25ca99eb88..2cec3549c7a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, 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 @@ -219,12 +219,12 @@ protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) { } /** - * Report an error at the given position using the provided arguments. + * Report a warning at the given position using the provided arguments. * * @param pos position in input buffer. * @param key error key to report. */ - protected void lexWarning(int pos, JCDiagnostic.Warning key) { + protected void lexWarning(int pos, JCDiagnostic.LintWarning key) { DiagnosticPosition dp = new SimpleDiagnosticPosition(pos) ; log.warning(dp, key); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Warner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Warner.java index 7b993c1bf16..3da0be49d33 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Warner.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Warner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -42,8 +42,8 @@ public class Warner { private DiagnosticPosition pos = null; protected boolean warned = false; - private EnumSet nonSilentLintSet = EnumSet.noneOf(LintCategory.class); - private EnumSet silentLintSet = EnumSet.noneOf(LintCategory.class); + private EnumSet nonSilentLintSet = LintCategory.newEmptySet(); + private EnumSet silentLintSet = LintCategory.newEmptySet(); public DiagnosticPosition pos() { return pos; diff --git a/src/jdk.compiler/share/man/javac.md b/src/jdk.compiler/share/man/javac.md index 7761cde2b58..3edbeda6eca 100644 --- a/src/jdk.compiler/share/man/javac.md +++ b/src/jdk.compiler/share/man/javac.md @@ -1667,7 +1667,7 @@ internal and subject to change at any time. public static int m() { try { throw new NullPointerException(); - } catch (NullPointerException(); { + } catch (NullPointerException e) { System.err.println("Caught NullPointerException."); return 1; } finally { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/AccessFlags.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/AccessFlags.java index 2f310effc87..66ebd6551a4 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/AccessFlags.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/AccessFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -75,9 +75,4 @@ public void printOn(PrintStream tty) { if (isStrict ()) tty.print("strict " ); if (isSynthetic ()) tty.print("synthetic " ); } - - // get flags written to .class files - public int getStandardFlags() { - return (int) (flags & JVM_ACC_WRITTEN_FLAGS); - } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java index 25f40ec443f..7f9a6b4b49d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -98,16 +98,7 @@ public interface ClassConstants public static final long JVM_ACC_ENUM = 0x4000; /* field is declared as element of enum */ - // from accessFlags.hpp - hotspot internal flags - - // flags actually put in .class file - public static final long JVM_ACC_WRITTEN_FLAGS = 0x00007FFF; - - // flags accepted by set_field_flags - public static final long JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS; - // from jvm.h - public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java index c6916bc52ef..df6fb9f2a9a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java @@ -353,9 +353,10 @@ record WildcardElement(String name, String label, ValueDescriptor field) { var subFields = we.field().getFields().reversed(); if (!subFields.isEmpty() && !KNOWN_TYPES.contains(we.field().getTypeName())) { for (ValueDescriptor subField : subFields) { - String n = we.name + "." + subField.getName(); - String l = we.label + " : " + makeLabel(subField, false); - if (stack.size() < 2) { // Limit depth to 2 + // Limit depth to 2 + if (!we.name.contains(".")) { + String n = we.name + "." + subField.getName(); + String l = we.label + " : " + makeLabel(subField, false); stack.push(new WildcardElement(n, l, subField)); } } @@ -369,7 +370,6 @@ record WildcardElement(String name, String label, ValueDescriptor field) { FieldBuilder fb = new FieldBuilder(eventTypes, type, we.name()); Field field = fb.build().getFirst(); field.label = we.label; - field.index = result.size(); field.visible = true; field.sourceFields.add(field); result.add(field); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/Function.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/Function.java index 29d55e95673..0c9ca96ee20 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/Function.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/Function.java @@ -89,7 +89,7 @@ public static Function create(Field field) { return createPercentile(field, 0.99); } if (aggregator == Aggregator.P999) { - return createPercentile(field, 0.9999); + return createPercentile(field, 0.999); } if (aggregator == Aggregator.MAXIMUM) { return new Maximum(); @@ -175,9 +175,9 @@ public void add(Object value) { @Override public Object result() { if (count != 0) { - long s = seconds / count; - long n = nanos / count; - return Duration.ofSeconds(s, n); + double total = 1_000_000_000.0 * seconds + nanos; + double average = total / count; + return Duration.ofNanos(Math.round(average)); } else { return null; } @@ -578,7 +578,7 @@ public Object result() { double doubleIndex = (size + 1) * percentile; int valueIndex = (int) doubleIndex - 1; int valueNextIndex = (int) doubleIndex; - double fraction = doubleIndex - valueIndex; + double fraction = doubleIndex - (int) doubleIndex; if (valueIndex < 0) { return numbers.getFirst(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryResolver.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryResolver.java index 4d947eea9a5..1b68a038a17 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryResolver.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryResolver.java @@ -98,11 +98,19 @@ public List resolve() throws QueryException { resolveGroupBy(); resolveOrderBy(); resolveWhere(); + applyIndex(); applyColumn(); applyFormat(); return resultFields; } + private void applyIndex() { + int index = 0; + for (Field field : resultFields) { + field.index = index++; + } + } + private void resolveWhere() throws QuerySyntaxException { for (Condition condition : where) { List fields = new ArrayList<>(); @@ -238,7 +246,6 @@ private Field addField(String name, List types) throws QueryExcept } } for (Field field: fields) { - field.index = resultFields.size(); primary.sourceFields.add(field); // Convert to String if field data types mismatch if (mixedTypes) { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java index 3ef42fb9aa0..60014e2bbd7 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java @@ -24,6 +24,9 @@ */ package jdk.tools.jlink.internal.runtimelink; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -49,6 +52,7 @@ public class JimageDiffGenerator { public interface ImageResource extends AutoCloseable { public List getEntries(); public byte[] getResourceBytes(String name); + public InputStream getResource(String name); } /** @@ -71,7 +75,6 @@ public List generateDiff(ImageResource base, ImageResource image) resources.addAll(image.getEntries()); baseResources = base.getEntries(); for (String item: baseResources) { - byte[] baseBytes = base.getResourceBytes(item); // First check that every item in the base image exist in // the optimized image as well. If it does not, it's a removed // item in the optimized image. @@ -82,19 +85,18 @@ public List generateDiff(ImageResource base, ImageResource image) ResourceDiff.Builder builder = new ResourceDiff.Builder(); ResourceDiff diff = builder.setKind(ResourceDiff.Kind.REMOVED) .setName(item) - .setResourceBytes(baseBytes) + .setResourceBytes(base.getResourceBytes(item)) .build(); diffs.add(diff); continue; } // Verify resource bytes are equal if present in both images - boolean contentEquals = Arrays.equals(baseBytes, image.getResourceBytes(item)); - if (!contentEquals) { + if (!compareStreams(base.getResource(item), image.getResource(item))) { // keep track of original bytes (non-optimized) ResourceDiff.Builder builder = new ResourceDiff.Builder(); ResourceDiff diff = builder.setKind(ResourceDiff.Kind.MODIFIED) .setName(item) - .setResourceBytes(baseBytes) + .setResourceBytes(base.getResourceBytes(item)) .build(); diffs.add(diff); } @@ -112,4 +114,51 @@ public List generateDiff(ImageResource base, ImageResource image) return diffs; } + /** + * Compare the contents of the two input streams (byte-by-byte). + * + * @param is1 The first input stream + * @param is2 The second input stream + * @return {@code true} iff the two streams contain the same number of + * bytes and each byte of the streams are equal. {@code false} + * otherwise. + */ + private boolean compareStreams(InputStream is1, InputStream is2) { + byte[] buf1 = new byte[1024]; + byte[] buf2 = new byte[1024]; + int bytesRead1, bytesRead2 = 0; + try { + try (is1; is2) { + while ((bytesRead1 = is1.read(buf1)) != -1 && + (bytesRead2 = is2.read(buf2)) != -1) { + if (bytesRead1 != bytesRead2) { + return false; + } + if (bytesRead1 == buf1.length) { + if (!Arrays.equals(buf1, buf2)) { + return false; + } + } else { + for (int i = 0; i < bytesRead1; i++) { + if (buf1[i] != buf2[i]) { + return false; + } + } + } + } + // ensure we read both to the end + if (bytesRead1 == -1) { + bytesRead2 = is2.read(buf2); + if (bytesRead2 != -1) { + return false; + } + return true; + } + } + } catch (IOException e) { + throw new UncheckedIOException("IO exception when comparing bytes", e); + } + return false; + } + } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java index 910fe57b75a..c4c16579906 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java @@ -25,6 +25,7 @@ package jdk.tools.jlink.internal.runtimelink; +import java.io.InputStream; import java.util.List; import java.util.Objects; @@ -56,4 +57,9 @@ public byte[] getResourceBytes(String name) { return pool.findEntry(name).orElseThrow().contentBytes(); } + @Override + public InputStream getResource(String name) { + return pool.findEntry(name).orElseThrow().content(); + } + } diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/FreeInteractiveLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/FreeInteractiveLayoutManager.java new file mode 100644 index 00000000000..7aec57ec2a0 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/FreeInteractiveLayoutManager.java @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package com.sun.hotspot.igv.hierarchicallayout; + +import static com.sun.hotspot.igv.hierarchicallayout.LayoutNode.LAYOUT_NODE_DEGREE_COMPARATOR; +import com.sun.hotspot.igv.layout.Link; +import com.sun.hotspot.igv.layout.Vertex; +import java.awt.Point; +import java.util.*; + +public class FreeInteractiveLayoutManager extends LayoutManager implements LayoutMover { + + private boolean cutEdges = false; + + private static final int LINE_OFFSET = 10; + + private Map layoutNodes; + + private LayoutGraph prevGraph; + + private final Random random = new Random(42); + + // Constants for offsets and displacements + private static final int MAX_OFFSET_AROUND_NEIGHBOR = 200; // Max offset for random positioning around a neighbor + private static final int MAX_OFFSET_AROUND_ORIGIN = 200; // Max offset for random positioning around origin + private static final int DISPLACEMENT_RANGE_BARYCENTER = 100; // Displacement range for barycenter calculation + private static final int DISPLACEMENT_RANGE_SINGLE = 200; + + // Create a comparator to sort nodes by the number of unassigned neighbors + private final Comparator LeastUnassignedNeighborsComparator = Comparator.comparingInt(node -> { + Vertex vertex = node.getVertex(); + int unassignedNeighbors = 0; + for (Vertex neighborVertex : prevGraph.getNeighborVertices(vertex)) { + if (!layoutNodes.containsKey(neighborVertex)) { + unassignedNeighbors++; + } + } + return unassignedNeighbors; + }); + + public FreeInteractiveLayoutManager() { + this.cutEdges = false; + this.layoutNodes = new HashMap<>(); + this.prevGraph = null; + } + + @Override + public void moveLink(Point linkPos, int shiftX) {} + + @Override + public void moveVertices(Set movedVertices) { + for (Vertex v : movedVertices) { + moveVertex(v); + } + } + + @Override + public void moveVertex(Vertex vertex) { + assert prevGraph.containsVertex(vertex); + LayoutNode layoutNode = layoutNodes.get(vertex); + layoutNode.setX(vertex.getPosition().x); + layoutNode.setY(vertex.getPosition().y); + for (Link link : prevGraph.getAllLinks(vertex)) { + setLinkControlPoints(link); + } + } + + @Override + public boolean isFreeForm() { + return true; + } + + public void setCutEdges(boolean enable) { + this.cutEdges = enable; + } + + @Override + public void doLayout(LayoutGraph graph) { + prevGraph = graph; + if (layoutNodes.isEmpty()) { + HierarchicalLayoutManager manager = new HierarchicalLayoutManager(); + manager.doLayout(graph); + for (LayoutNode node : graph.getLayoutNodes()) { + node.initSize(); + layoutNodes.put(node.getVertex(), node); + } + graph.clearLayout(); + } else { + // add new vertices to layoutNodes, x/y from barycenter + List newLayoutNodes = new ArrayList<>(); + + // Set up layout nodes for each vertex + for (Vertex vertex : prevGraph.getVertices()) { + if (!layoutNodes.containsKey(vertex)) { + LayoutNode addedNode = new LayoutNode(vertex); + addedNode.initSize(); + newLayoutNodes.add(addedNode); + } + } + + positionNewLayoutNodes(newLayoutNodes); + } + + // Write back vertices + for (Vertex vertex : prevGraph.getVertices()) { + LayoutNode layoutNode = layoutNodes.get(vertex); + layoutNode.setVertex(vertex); + vertex.setPosition(new Point(layoutNode.getLeft(), layoutNode.getTop())); + } + + // Write back links + for (Link link : prevGraph.getLinks()) { + setLinkControlPoints(link); + } + } + + public void positionNewLayoutNodes(List newLayoutNodes) { + // First pass: Initial positioning based on unassigned neighbors + newLayoutNodes.sort(LeastUnassignedNeighborsComparator); + + for (LayoutNode node : newLayoutNodes) { + Vertex vertex = node.getVertex(); + + // Gather assigned neighbors + List assignedNeighbors = new ArrayList<>(); + for (Vertex neighborVertex : prevGraph.getNeighborVertices(vertex)) { + if (layoutNodes.containsKey(neighborVertex)) { + assignedNeighbors.add(layoutNodes.get(neighborVertex)); + } + } + + if (!assignedNeighbors.isEmpty()) { + if (assignedNeighbors.size() == 1) { + // Single neighbor: position around the neighbor + setPositionAroundSingleNode(node, assignedNeighbors.get(0), DISPLACEMENT_RANGE_SINGLE); + } else { + // Multiple neighbors: Calculate barycenter with displacement + calculateBarycenterWithDisplacement(node, assignedNeighbors, DISPLACEMENT_RANGE_BARYCENTER); + } + } else { + // No neighbors: Position randomly around (0, 0) + setRandomPositionAroundOrigin(node, random); + } + + // Add the new node to the layout + layoutNodes.put(vertex, node); + } + + // Second pass: Refine positions based on neighbor degree + newLayoutNodes.sort(LAYOUT_NODE_DEGREE_COMPARATOR.reversed()); + + // Collect all nodes (existing and new) + Collection allNodes = layoutNodes.values(); + + for (LayoutNode node : newLayoutNodes) { + Vertex vertex = node.getVertex(); + + // Gather assigned neighbors + List assignedNeighbors = new ArrayList<>(); + for (Vertex neighborVertex : prevGraph.getNeighborVertices(vertex)) { + if (layoutNodes.containsKey(neighborVertex)) { + assignedNeighbors.add(layoutNodes.get(neighborVertex)); + } + } + + if (!assignedNeighbors.isEmpty()) { + // Refine position based on force-based method + applyForceBasedAdjustment(node, assignedNeighbors, allNodes); + } + + // Ensure node's position remains updated in the layout + layoutNodes.put(vertex, node); + } + } + + /** + * Applies a force-based adjustment to the position of a given layout node + * based on repulsive forces from all other nodes and attractive forces from its assigned neighbors. + *

    + * This method simulates a physical system where nodes repel each other to maintain spacing + * and are pulled towards their neighbors to maintain connectivity. The forces are calculated + * using Coulomb's law for repulsion and Hooke's law for attraction. The system iterates for + * a fixed number of iterations to stabilize the position of the node. + * + * @param node The node whose position is being adjusted. + * @param assignedNeighbors A list of neighboring nodes that attract this node. + * @param allNodes A collection of all nodes in the layout, used for repulsive forces. + */ + private void applyForceBasedAdjustment(LayoutNode node, List assignedNeighbors, Collection allNodes) { + // Constants for force-based adjustment + final int ITERATIONS = 50; // Number of simulation iterations + final double REPULSION_CONSTANT = 1000; // Magnitude of repulsive forces (Coulomb's law) + final double SPRING_CONSTANT = 0.2; // Strength of attractive forces to neighbors (Hooke's law) + final double DAMPING = 0.8; // Factor to reduce displacement and ensure stability + final double IDEAL_LENGTH = 100; // Desired distance between a node and its neighbors + final double MAX_FORCE = 1000; // Upper limit for the magnitude of applied forces + final double CONVERGENCE_THRESHOLD = 0.01; // Force threshold for stopping early + + double posX = node.getX(); + double posY = node.getY(); + double dx = 0, dy = 0; // Displacement + + for (int i = 0; i < ITERATIONS; i++) { + double netForceX = 0; + double netForceY = 0; + + // Repulsive forces from all other nodes + for (LayoutNode otherNode : allNodes) { + if (otherNode == node) continue; // Skip self + + double deltaX = posX - otherNode.getX(); + double deltaY = posY - otherNode.getY(); + double distanceSquared = deltaX * deltaX + deltaY * deltaY; + double distance = Math.sqrt(distanceSquared); + + // Avoid division by zero by introducing a minimum distance + if (distance < 1e-6) { + deltaX = random.nextDouble() * 0.1 - 0.05; + deltaY = random.nextDouble() * 0.1 - 0.05; + distanceSquared = deltaX * deltaX + deltaY * deltaY; + distance = Math.sqrt(distanceSquared); + } + + // Repulsive force (Coulomb's law) + double repulsiveForce = REPULSION_CONSTANT / distanceSquared; + + // Normalize force to prevent large displacements + if (repulsiveForce > MAX_FORCE) repulsiveForce = MAX_FORCE; + + netForceX += (deltaX / distance) * repulsiveForce; + netForceY += (deltaY / distance) * repulsiveForce; + } + + // Attractive forces to assigned neighbors + for (LayoutNode neighbor : assignedNeighbors) { + double deltaX = neighbor.getX() - posX; + double deltaY = neighbor.getY() - posY; + double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + + if (distance < 1e-6) { + deltaX = random.nextDouble() * 0.1 - 0.05; + deltaY = random.nextDouble() * 0.1 - 0.05; + distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + } + + // Attractive force (Hooke's law) + double displacement = distance - IDEAL_LENGTH; + double attractiveForce = SPRING_CONSTANT * displacement; + + if (attractiveForce > MAX_FORCE) attractiveForce = MAX_FORCE; + + netForceX += (deltaX / distance) * attractiveForce; + netForceY += (deltaY / distance) * attractiveForce; + } + + // Apply damping and update displacement + dx = (dx + netForceX) * DAMPING; + dy = (dy + netForceY) * DAMPING; + + // Scale displacement if it's too large + double displacementMagnitude = Math.sqrt(dx * dx + dy * dy); + if (displacementMagnitude > MAX_FORCE) { + dx *= MAX_FORCE / displacementMagnitude; + dy *= MAX_FORCE / displacementMagnitude; + } + + // Update position + posX += dx; + posY += dy; + + // Stop early if the net force is negligible + if (Math.abs(netForceX) < CONVERGENCE_THRESHOLD && Math.abs(netForceY) < CONVERGENCE_THRESHOLD) { + break; + } + + // Validate position to avoid invalid or extreme values + if (Double.isNaN(posX) || Double.isInfinite(posX) || Double.isNaN(posY) || Double.isInfinite(posY)) { + posX = node.getX(); // Reset to original position + posY = node.getY(); + break; + } + } + + // Set final position + node.setX((int) Math.round(posX)); + node.setY((int) Math.round(posY)); + } + + // Utility method: position around a given node + private void setPositionAroundSingleNode(LayoutNode node, LayoutNode neighbor, int displacement) { + boolean neighborIsPredecessor = prevGraph.isPredecessorVertex(node.getVertex(), neighbor.getVertex()); + boolean neighborIsSuccessor = prevGraph.isSuccessorVertex(node.getVertex(), neighbor.getVertex()); + + int shiftY = 0; + if (neighborIsPredecessor) { + shiftY = displacement; + } else if (neighborIsSuccessor) { + shiftY = -displacement; + } + assert shiftY != 0; + + int randomY = neighbor.getY() + random.nextInt(MAX_OFFSET_AROUND_NEIGHBOR + 1) + shiftY; + int randomX = neighbor.getX() + random.nextInt(MAX_OFFSET_AROUND_NEIGHBOR + 1); + node.setX(randomX); + node.setY(randomY); + } + + // Utility method: Random position around origin + private void setRandomPositionAroundOrigin(LayoutNode node, Random random) { + int randomX = random.nextInt(MAX_OFFSET_AROUND_ORIGIN + 1); + int randomY = random.nextInt(MAX_OFFSET_AROUND_ORIGIN + 1); + node.setX(randomX); + node.setY(randomY); + } + + // Utility method: Calculate barycenter with displacement + private void calculateBarycenterWithDisplacement(LayoutNode node, List neighbors, int displacementRange) { + double barycenterX = 0, barycenterY = 0; + for (LayoutNode neighbor : neighbors) { + barycenterX += neighbor.getX(); + barycenterY += neighbor.getY(); + } + barycenterX /= neighbors.size(); + barycenterY /= neighbors.size(); + + // Add random displacement for slight separation + int displacementX = random.nextInt(displacementRange + 1); + int displacementY = random.nextInt(displacementRange + 1); + node.setX((int) barycenterX + displacementX); + node.setY((int) barycenterY + displacementY); + } + + /** + * Sets control points for a given link based on its start and end layout nodes. + *

    + * Calculates the start and end points, applies offsets for curvature, and updates + * the link's control points. + * + * @param link The link to process. + */ + private void setLinkControlPoints(Link link) { + if (link.getFrom().getVertex() == link.getTo().getVertex()) return; // Skip self-links + + LayoutNode from = layoutNodes.get(link.getFrom().getVertex()); + from.setVertex(link.getFrom().getVertex()); + from.updateSize(); + + LayoutNode to = layoutNodes.get(link.getTo().getVertex()); + to.setVertex(link.getTo().getVertex()); + to.updateSize(); + + Point startPoint = new Point(from.getLeft() + link.getFrom().getRelativePosition().x, from.getBottom()); + Point endPoint = new Point(to.getLeft() + link.getTo().getRelativePosition().x, to.getTop()); + + List controlPoints = new ArrayList<>(); + controlPoints.add(startPoint); + controlPoints.add(new Point(startPoint.x, startPoint.y + LINE_OFFSET)); + controlPoints.add(new Point(endPoint.x, endPoint.y - LINE_OFFSET)); + controlPoints.add(endPoint); + + link.setControlPoints(controlPoints); + } +} diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java index e2d6bf18039..cb9487ae828 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java @@ -53,6 +53,11 @@ public void setCutEdges(boolean enable) { maxLayerLength = enable ? 10 : -1; } + @Override + public boolean isFreeForm() { + return false; + } + @Override public void doLayout(LayoutGraph layoutGraph) { layoutGraph.initializeLayout(); diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutGraph.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutGraph.java index 64d96412467..956d72924b9 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutGraph.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,7 @@ public Collection getLayoutNodes() { * Retrieves a combined list of all nodes in the graph, * including both layout nodes and dummy nodes. * - * @return An unmodifiable list containing all nodes in the graph. + * @return An unmodifiable list containing all nodes in the graph */ public List getAllNodes() { List allNodes = new ArrayList<>(); @@ -447,6 +447,63 @@ public List getOutputLinks(Vertex vertex) { return outputLinks; } + /** + * Checks if the given predecessorVertex is a direct predecessor of the specified vertex. + * + * @param vertex The vertex to check for predecessors. + * @param predecessorVertex The vertex to verify as a predecessor of the given vertex. + * @return true if predecessorVertex is a direct predecessor of vertex, false otherwise. + */ + public boolean isPredecessorVertex(Vertex vertex, Vertex predecessorVertex) { + for (Port inputPort : inputPorts.getOrDefault(vertex, Collections.emptySet())) { + for (Link inputLink : portLinks.getOrDefault(inputPort, Collections.emptySet())) { + Vertex fromVertex = inputLink.getFrom().getVertex(); + if (fromVertex.equals(predecessorVertex)) { + return true; + } + } + } + return false; + } + + /** + * Checks if the given successorVertex is a direct successor of the specified vertex. + * + * @param vertex The vertex to check for successors. + * @param successorVertex The vertex to verify as a successor of the given vertex. + * @return true if successorVertex is a direct successor of vertex, false otherwise. + */ + public boolean isSuccessorVertex(Vertex vertex, Vertex successorVertex) { + for (Port outputPort : outputPorts.getOrDefault(vertex, Collections.emptySet())) { + for (Link outputLink : portLinks.getOrDefault(outputPort, Collections.emptySet())) { + Vertex toVertex = outputLink.getTo().getVertex(); + if (toVertex.equals(successorVertex)) { + return true; + } + } + } + return false; + } + + public List getNeighborVertices(Vertex vertex) { + List neighborVertices = new ArrayList<>(); + for (Port inputPort : inputPorts.getOrDefault(vertex, Collections.emptySet())) { + for (Link inputLink : portLinks.getOrDefault(inputPort, Collections.emptySet())) { + Vertex fromVertex = inputLink.getFrom().getVertex(); + assert fromVertex != null; + neighborVertices.add(fromVertex); + } + } + for (Port outputPort : outputPorts.getOrDefault(vertex, Collections.emptySet())) { + for (Link outputLink : portLinks.getOrDefault(outputPort, Collections.emptySet())) { + Vertex toVertex = outputLink.getTo().getVertex(); + assert toVertex != null; + neighborVertices.add(toVertex); + } + } + return neighborVertices; + } + public List getAllLinks(Vertex vertex) { List allLinks = new ArrayList<>(); diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutMover.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutMover.java index 19f24f1f7e6..48599d78d75 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutMover.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutMover.java @@ -49,5 +49,7 @@ public interface LayoutMover { * @param movedVertex The vertex to be moved. */ void moveVertex(Vertex movedVertex); + + boolean isFreeForm(); } diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutNode.java b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutNode.java index 9ad0c70b912..2816115080e 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutNode.java +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LayoutNode.java @@ -107,12 +107,7 @@ public LayoutNode() { this(null); } - /** - * Initializes the size and margins of the node. - * If the node represents a real vertex, it uses the vertex's size. - * Dummy nodes use default dimensions. - */ - public void initSize() { + public void updateSize() { if (vertex == null) { height = DUMMY_HEIGHT; width = DUMMY_WIDTH; @@ -121,6 +116,15 @@ public void initSize() { height = size.height; width = size.width; } + } + + /** + * Initializes the size and margins of the node. + * If the node represents a real vertex, it uses the vertex's size. + * Dummy nodes use default dimensions. + */ + public void initSize() { + updateSize(); topMargin = 0; bottomMargin = 0; leftMargin = 0; diff --git a/src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/Settings.java b/src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/Settings.java index 41af4a1d262..480fb43ea5b 100644 --- a/src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/Settings.java +++ b/src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/Settings.java @@ -37,6 +37,7 @@ public static class DefaultView { public static final int CLUSTERED_SEA_OF_NODES = 1; public static final int CONTROL_FLOW_GRAPH = 2; public static final int STABLE_SEA_OF_NODES = 3; + public static final int INTERACTIVE_FREE_NODES = 4; } public static final String NODE_TEXT = "nodeText"; diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java index 90d5e0ac424..99ae3380bb3 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java @@ -89,6 +89,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl private final Map> outputSlotToLineWidget = new HashMap<>(); private final Map> inputSlotToLineWidget = new HashMap<>(); + private final FreeInteractiveLayoutManager freeInteractiveLayoutManager; private final HierarchicalStableLayoutManager hierarchicalStableLayoutManager; private HierarchicalLayoutManager seaLayoutManager; private LayoutMover layoutMover; @@ -511,6 +512,7 @@ public void ancestorResized(HierarchyEvent e) { } }); + freeInteractiveLayoutManager = new FreeInteractiveLayoutManager(); hierarchicalStableLayoutManager = new HierarchicalStableLayoutManager(); seaLayoutManager = new HierarchicalLayoutManager(); @@ -643,6 +645,8 @@ public void movementStarted(Widget widget) { widget.bringToFront(); startLayerY = widget.getLocation().y; hasMoved = false; // Reset the movement flag + if (layoutMover.isFreeForm()) return; + Set

    selectedFigures = model.getSelectedFigures(); if (selectedFigures.size() == 1) { Figure selectedFigure = selectedFigures.iterator().next(); @@ -702,8 +706,12 @@ public void setNewLocation(Widget widget, Point location) { hasMoved = true; // Mark that a movement occurred int shiftX = location.x - widget.getLocation().x; - int shiftY = magnetToStartLayerY(widget, location); - + int shiftY; + if (layoutMover.isFreeForm()) { + shiftY = location.y - widget.getLocation().y; + } else { + shiftY = magnetToStartLayerY(widget, location); + } List
    selectedFigures = new ArrayList<>( model.getSelectedFigures()); selectedFigures.sort(Comparator.comparingInt(f -> f.getPosition().x)); for (Figure figure : selectedFigures) { @@ -713,12 +721,15 @@ public void setNewLocation(Widget widget, Point location) { if (inputSlotToLineWidget.containsKey(inputSlot)) { for (LineWidget lw : inputSlotToLineWidget.get(inputSlot)) { assert lw != null; - Point toPt = lw.getTo(); Point fromPt = lw.getFrom(); - if (toPt != null && fromPt != null) { - int xTo = toPt.x + shiftX; - int yTo = toPt.y + shiftY; - lw.setTo(new Point(xTo, yTo)); + Point toPt = lw.getTo(); + if (toPt == null || fromPt == null) { + continue; + } + int xTo = toPt.x + shiftX; + int yTo = toPt.y + shiftY; + lw.setTo(new Point(xTo, yTo)); + if (!layoutMover.isFreeForm()) { lw.setFrom(new Point(fromPt.x + shiftX, fromPt.y)); LineWidget pred = lw.getPredecessor(); pred.setTo(new Point(pred.getTo().x + shiftX, pred.getTo().y)); @@ -735,10 +746,13 @@ public void setNewLocation(Widget widget, Point location) { assert lw != null; Point fromPt = lw.getFrom(); Point toPt = lw.getTo(); - if (toPt != null && fromPt != null) { - int xFrom = fromPt.x + shiftX; - int yFrom = fromPt.y + shiftY; - lw.setFrom(new Point(xFrom, yFrom)); + if (toPt == null || fromPt == null) { + continue; + } + int xFrom = fromPt.x + shiftX; + int yFrom = fromPt.y + shiftY; + lw.setFrom(new Point(xFrom, yFrom)); + if (!layoutMover.isFreeForm()) { lw.setTo(new Point(toPt.x + shiftX, toPt.y)); for (LineWidget succ : lw.getSuccessors()) { succ.setFrom(new Point(succ.getFrom().x + shiftX, succ.getFrom().y)); @@ -753,10 +767,12 @@ public void setNewLocation(Widget widget, Point location) { ActionFactory.createDefaultMoveProvider().setNewLocation(fw, newLocation); } - FigureWidget fw = getWidget(selectedFigures.iterator().next()); - pointerWidget.setVisible(true); - Point newLocation = new Point(fw.getLocation().x + shiftX -3, fw.getLocation().y + shiftY); - ActionFactory.createDefaultMoveProvider().setNewLocation(pointerWidget, newLocation); + if (selectedFigures.size() == 1 && !layoutMover.isFreeForm()) { + FigureWidget fw = getWidget(selectedFigures.iterator().next()); + pointerWidget.setVisible(true); + Point newLocation = new Point(fw.getLocation().x + shiftX -3, fw.getLocation().y + shiftY); + ActionFactory.createDefaultMoveProvider().setNewLocation(pointerWidget, newLocation); + } connectionLayer.revalidate(); connectionLayer.repaint(); } @@ -834,7 +850,9 @@ private void relayout() { Set
    visibleFigures = getVisibleFigures(); Set visibleConnections = getVisibleConnections(); - if (getModel().getShowStableSea()) { + if (getModel().getShowFreeInteractive()) { + doFreeInteractiveLayout(visibleFigures, visibleConnections); + } else if (getModel().getShowStableSea()) { doStableSeaLayout(visibleFigures, visibleConnections); } else if (getModel().getShowSea()) { doSeaLayout(visibleFigures, visibleConnections); @@ -904,6 +922,12 @@ private boolean isVisibleFigureConnection(FigureConnection figureConnection) { return w1.isVisible() && w2.isVisible(); } + private void doFreeInteractiveLayout(Set
    visibleFigures, Set visibleConnections) { + layoutMover = freeInteractiveLayoutManager; + freeInteractiveLayoutManager.setCutEdges(model.getCutEdges()); + freeInteractiveLayoutManager.doLayout(new LayoutGraph(visibleConnections, visibleFigures)); + } + private void doStableSeaLayout(Set
    visibleFigures, Set visibleConnections) { layoutMover = null; boolean enable = model.getCutEdges(); @@ -1108,6 +1132,52 @@ private void processOutputSlot(OutputSlot outputSlot, List con } } + private void processFreeForm(OutputSlot outputSlot, List connections) { + for (FigureConnection connection : connections) { + if (isVisibleFigureConnection(connection)) { + boolean isBold = false; + boolean isDashed = true; + boolean isVisible = true; + if (connection.getStyle() == Connection.ConnectionStyle.BOLD) { + isBold = true; + } else if (connection.getStyle() == Connection.ConnectionStyle.INVISIBLE) { + isVisible = false; + } + if (connection.getStyle() != Connection.ConnectionStyle.DASHED) { + isDashed = false; + } + + + List controlPoints = connection.getControlPoints(); + if (controlPoints.size() <= 2) continue; + Point firstPoint = controlPoints.get(0); // First point + Point lastPoint = controlPoints.get(controlPoints.size() - 1); // Last point + List connectionList = new ArrayList<>(Collections.singleton(connection)); + LineWidget line = new LineWidget(this, outputSlot, connectionList, firstPoint, lastPoint, null, isBold, isDashed); + line.setFromControlYOffset(50); + line.setToControlYOffset(-50); + line.setVisible(isVisible); + connectionLayer.addChild(line); + + addObject(new ConnectionSet(connectionList), line); + line.getActions().addAction(hoverAction); + + if (outputSlotToLineWidget.containsKey(outputSlot)) { + outputSlotToLineWidget.get(outputSlot).add(line); + } else { + outputSlotToLineWidget.put(outputSlot, new HashSet<>(Collections.singleton(line))); + } + + InputSlot inputSlot = connection.getInputSlot(); + if (inputSlotToLineWidget.containsKey(inputSlot)) { + inputSlotToLineWidget.get(inputSlot).add(line); + } else { + inputSlotToLineWidget.put(inputSlot, new HashSet<>(Collections.singleton(line))); + } + } + } + } + private void processBlockConnection(BlockConnection blockConnection) { boolean isDashed = blockConnection.getStyle() == Connection.ConnectionStyle.DASHED; boolean isBold = blockConnection.getStyle() == Connection.ConnectionStyle.BOLD; @@ -1281,7 +1351,11 @@ private void rebuildConnectionLayer() { for (Figure figure : getModel().getDiagram().getFigures()) { for (OutputSlot outputSlot : figure.getOutputSlots()) { List connectionList = new ArrayList<>(outputSlot.getConnections()); - processOutputSlot(outputSlot, connectionList, 0, null, null); + if (layoutMover != null && layoutMover.isFreeForm()) { + processFreeForm(outputSlot, connectionList); + } else { + processOutputSlot(outputSlot, connectionList, 0, null, null); + } } } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java index e6cdbebbe52..710c5c125f6 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java @@ -63,6 +63,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene private final ChangedEvent selectedNodesChangedEvent = new ChangedEvent<>(this); private final ChangedEvent hiddenNodesChangedEvent = new ChangedEvent<>(this); private ChangedListener titleChangedListener = g -> {}; + private boolean showFreeInteractive; private boolean showStableSea; private boolean showSea; private boolean showBlocks; @@ -104,6 +105,17 @@ public void setGlobalSelection(boolean enable, boolean fire) { } } + public boolean getShowFreeInteractive() { + return showFreeInteractive; + } + + public void setShowFreeInteractive(boolean enable) { + showFreeInteractive = enable; + if (enable) { + diagramChangedEvent.fire(); + } + } + public boolean getShowStableSea() { return showStableSea; } @@ -224,6 +236,7 @@ public DiagramViewModel(InputGraph graph) { globalSelection = GlobalSelectionAction.get(GlobalSelectionAction.class).isSelected(); cutEdges = CutEdgesAction.get(CutEdgesAction.class).isSelected(); + showFreeInteractive = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.INTERACTIVE_FREE_NODES; showStableSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.STABLE_SEA_OF_NODES; showSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.SEA_OF_NODES; showBlocks = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES; @@ -266,7 +279,7 @@ public void setSelectedNodes(Set nodes) { for (String ignored : getPositions()) { colors.add(Color.black); } - if (nodes.size() >= 1) { + if (!nodes.isEmpty()) { for (Integer id : nodes) { if (id < 0) { id = -id; diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java index d067925fb87..ff51b8928f6 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java @@ -176,6 +176,11 @@ public void mouseMoved(MouseEvent e) {} toolBar.addSeparator(); ButtonGroup layoutButtons = new ButtonGroup(); + JToggleButton freeInteractiveLayoutButton = new JToggleButton(new EnableFreeLayoutAction(this)); + freeInteractiveLayoutButton.setSelected(diagramViewModel.getShowFreeInteractive()); + layoutButtons.add(freeInteractiveLayoutButton); + toolBar.add(freeInteractiveLayoutButton); + JToggleButton stableSeaLayoutButton = new JToggleButton(new EnableStableSeaLayoutAction(this)); stableSeaLayoutButton.setSelected(diagramViewModel.getShowStableSea()); layoutButtons.add(stableSeaLayoutButton); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableFreeLayoutAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableFreeLayoutAction.java new file mode 100644 index 00000000000..201fc51e15e --- /dev/null +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableFreeLayoutAction.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package com.sun.hotspot.igv.view.actions; + +import com.sun.hotspot.igv.view.EditorTopComponent; +import java.beans.PropertyChangeEvent; + +public class EnableFreeLayoutAction extends EnableLayoutAction { + + public EnableFreeLayoutAction(EditorTopComponent etc) { + super(etc); + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/view/images/dynamic.png"; + } + + @Override + protected String getDescription() { + return "Show dynamic free layout"; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + editor.getModel().setShowFreeInteractive(this.isSelected()); + } +} diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java index 93d16d35914..01ebb8ed9e3 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java @@ -30,14 +30,16 @@ import com.sun.hotspot.igv.layout.Vertex; import com.sun.hotspot.igv.util.StringUtils; import com.sun.hotspot.igv.view.DiagramScene; -import com.sun.hotspot.igv.view.actions.CustomSelectAction; import java.awt.*; +import java.awt.geom.CubicCurve2D; import java.awt.geom.Line2D; import java.util.*; import java.util.List; import javax.swing.JPopupMenu; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; + +import com.sun.hotspot.igv.view.actions.CustomSelectAction; import org.netbeans.api.visual.action.ActionFactory; import org.netbeans.api.visual.action.PopupMenuProvider; import org.netbeans.api.visual.action.SelectProvider; @@ -70,6 +72,8 @@ public class LineWidget extends Widget implements PopupMenuProvider { private final boolean isBold; private final boolean isDashed; private boolean needToInitToolTipText = true; + private int fromControlYOffset; + private int toControlYOffset; public LineWidget(DiagramScene scene, OutputSlot s, List connections, Point from, Point to, LineWidget predecessor, boolean isBold, boolean isDashed) { super(scene); @@ -172,6 +176,16 @@ public void setTo(Point to) { computeClientArea(); } + public void setFromControlYOffset(int fromControlYOffset) { + this.fromControlYOffset = fromControlYOffset; + computeClientArea(); + } + + public void setToControlYOffset(int toControlYOffset) { + this.toControlYOffset = toControlYOffset; + computeClientArea(); + } + public Point getFrom() { return from; } @@ -225,7 +239,41 @@ protected void paintWidget() { g.setStroke(new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)); } - g.drawLine(from.x, from.y, to.x, to.y); + // Define S-shaped curve with control points + if (fromControlYOffset != 0 && toControlYOffset != 0) { + if (from.y < to.y) { // non-reversed edges + if (Math.abs(from.x - to.x) > 10) { + CubicCurve2D.Float sShape = new CubicCurve2D.Float(); + sShape.setCurve(from.x, from.y, + from.x, from.y + fromControlYOffset, + to.x, to.y + toControlYOffset, + to.x, to.y); + g.draw(sShape); + } else { + g.drawLine(from.x, from.y, to.x, to.y); + } + } else { // reverse edges + if (from.x - to.x > 0) { + CubicCurve2D.Float sShape = new CubicCurve2D.Float(); + sShape.setCurve(from.x, from.y, + from.x - 150, from.y + fromControlYOffset, + to.x + 150, to.y + toControlYOffset, + to.x, to.y); + g.draw(sShape); + } else { + // add x offset + CubicCurve2D.Float sShape = new CubicCurve2D.Float(); + sShape.setCurve(from.x, from.y, + from.x + 150, from.y + fromControlYOffset, + to.x - 150, to.y + toControlYOffset, + to.x, to.y); + g.draw(sShape); + } + } + } else { + // Fallback to straight line if control points are not set + g.drawLine(from.x, from.y, to.x, to.y); + } boolean sameFrom = false; boolean sameTo = successors.isEmpty(); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/dynamic.png b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/dynamic.png new file mode 100644 index 00000000000..781b98176f8 Binary files /dev/null and b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/dynamic.png differ diff --git a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp index 5dc43fb543f..9cadc91aeb9 100644 --- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp +++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -289,4 +289,7 @@ TEST(globalDefinitions, format_specifiers) { check_format(INTPTR_FORMAT, (intptr_t)0x123, "0x" LP64_ONLY("00000000") "00000123"); check_format(PTR_FORMAT, (uintptr_t)0x123, "0x" LP64_ONLY("00000000") "00000123"); + + // Check all platforms print this compatibly without leading 0x. + check_format(UINT64_FORMAT_0, (u8)0x123, "0000000000000123"); } diff --git a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java index a974a09d615..017242c6d9e 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -71,6 +71,7 @@ public abstract class CiReplayBase { "-XX:-BackgroundCompilation", "-XX:CompileCommand=inline,java.io.PrintStream::*", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", // extra profile data as a stress test "-XX:+CICountNative", "-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError", + "-XX:-SegmentedCodeCache", REPLAY_FILE_OPTION}; private static final String[] REPLAY_OPTIONS = new String[]{DISABLE_COREDUMP_ON_CRASH, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", diff --git a/test/hotspot/jtreg/compiler/sharedstubs/SharedTrampolineTest.java b/test/hotspot/jtreg/compiler/sharedstubs/SharedTrampolineTest.java index f1e4d18b93a..0ce62954db7 100644 --- a/test/hotspot/jtreg/compiler/sharedstubs/SharedTrampolineTest.java +++ b/test/hotspot/jtreg/compiler/sharedstubs/SharedTrampolineTest.java @@ -30,7 +30,7 @@ * * @requires vm.compiler2.enabled * @requires vm.opt.TieredCompilation == null - * @requires os.arch=="aarch64" | os.arch=="riscv64" + * @requires os.arch=="aarch64" * @requires vm.debug * * @run driver compiler.sharedstubs.SharedTrampolineTest -XX:-TieredCompilation diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java index 5891033fbd9..7f00fece7e6 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java @@ -39,6 +39,7 @@ * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc * @summary Test that vector reinterpret intrinsics work as intended. + * @requires os.arch != "riscv64" | vm.cpu.features ~= ".*rvv.*" * @library /test/lib / * @run main compiler.vectorapi.reshape.TestVectorReinterpret */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorizationNegativeScale.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorizationNegativeScale.java index 58464880070..4fc9f7d1ed1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorizationNegativeScale.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorizationNegativeScale.java @@ -25,7 +25,7 @@ * @test * @bug 8332827 * @summary [REDO] C2: crash in compiled code because of dependency on removed range check CastIIs - * + * @requires os.arch != "riscv64" | vm.cpu.features ~= ".*rvv.*" * @library /test/lib / * @run driver TestVectorizationNegativeScale * diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java index 574a680aceb..48fc6699fa2 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java @@ -85,15 +85,8 @@ private static void do_test(boolean CDS) throws IOException { output.shouldContain(tryReserveFor16bitMoveIntoQ3); } else if (Platform.isRISCV64()) { output.shouldContain(tryReserveForUnscaled); // unconditionally - if (CDS) { - output.shouldNotContain(tryReserveForZeroBased); - // bits 32..44 - output.shouldContain("reserve_between (range [0x0000000100000000-0x0000100000000000)"); - } else { - output.shouldContain(tryReserveForZeroBased); - // bits 32..44, but not lower than zero-based limit - output.shouldContain("reserve_between (range [0x0000000800000000-0x0000100000000000)"); - } + // bits 32..44 + output.shouldContain("reserve_between (range [0x0000000100000000-0x0000100000000000)"); // bits 44..64 output.shouldContain("reserve_between (range [0x0000100000000000-0xffffffffffffffff)"); } else if (Platform.isS390x()) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java b/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java new file mode 100644 index 00000000000..c478fad7cc2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8346457 + * @summary VM should not crash during AOT cache creation when encountering a + * class with VerifyError. + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @compile test-classes/BadLookupSwitch.jcod + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar badlookupswitch.jar BadLookupSwitch + * @run driver CreateAOTCacheVerifyError + */ + +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class CreateAOTCacheVerifyError { + + public static void main(String[] args) throws Exception { + String appJar = ClassFileInstaller.getJarPath("badlookupswitch.jar"); + String classList[] = { BadLookupSwitch.class.getName() }; + OutputAnalyzer out = TestCommon.testDump(appJar, classList); + out.shouldContain("Preload Warning: Verification failed for BadLookupSwitch"); + out.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod new file mode 100644 index 00000000000..4912479a8aa --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +class BadLookupSwitch { + 0xCAFEBABE; + 0; + 50; + [] { // Constant Pool + ; // first element is empty + class #12; // #1 at 0x0A + class #15; // #2 at 0x0D + Method #2 #4; // #3 at 0x10 + NameAndType #6 #5; // #4 at 0x15 + Utf8 "()V"; // #5 at 0x1A + Utf8 ""; // #6 at 0x20 + Utf8 "Code"; // #7 at 0x29 + Utf8 "ConstantValue"; // #8 at 0x30 + Utf8 "Exceptions"; // #9 at 0x40 + Utf8 "LineNumberTable"; // #10 at 0x4D + Utf8 "LocalVariables"; // #11 at 0x5F + Utf8 "BadLookupSwitch"; // #12 at 0x70 + Utf8 "SourceFile"; // #13 at 0x76 + Utf8 "f.java"; // #14 at 0x83 + Utf8 "java/lang/Object"; // #15 at 0x8C + Utf8 "m"; // #16 at 0x9F + Utf8 "StackMapTable"; // #17 + } // Constant Pool + + 0x0020; // access + #1;// this_cpx + #2;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [2] { // methods + { // Member at 0xAF + 0x0001; // access + #16; // name_cpx + #5; // sig_cpx + [] { // Attributes + Attr(#7) { // Code at 0xB7 + 1; // max_stack + 1; // max_locals + Bytes[29] { + 0x04AB00000000001B; // iconst_1; +/* right: + 0x0000000200000001; // lookupswitch 27 2 1 27 2 27; + 0x0000001B00000002; + 0x0000001B; +end right */ +// wrong: + 0x0000000200000002; // lookupswitch 27 2 2 27 1 27; + 0x0000001B00000001; + 0x0000001B; +// end wrong + 0xB1; // return + }; + [0] { // Traps + } // end Traps + [] { // Attributes + Attr(#17) { // StackMap + [] { // + 255b, 28, []{O,1}, []{}; + } + } // end StackMap + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0xD6 + 0x0000; // access + #6; // name_cpx + #5; // sig_cpx + [1] { // Attributes + Attr(#7) { // Code at 0xDE + 1; // max_stack + 1; // max_locals + Bytes[5] { + 0x2AB70003B1; + }; + [0] { // Traps + } // end Traps + [] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + } // Attributes +} // end class diff --git a/test/hotspot/jtreg/testlibrary/ctw/Makefile b/test/hotspot/jtreg/testlibrary/ctw/Makefile index 5c64c67d828..ea133f97621 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/Makefile +++ b/test/hotspot/jtreg/testlibrary/ctw/Makefile @@ -53,6 +53,7 @@ WB_CLASS_FILES := $(subst $(TESTLIBRARY_DIR)/,,$(WB_SRC_FILES)) WB_CLASS_FILES := $(patsubst %.java,%.class,$(WB_CLASS_FILES)) EXPORTS=--add-exports java.base/jdk.internal.jimage=ALL-UNNAMED \ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.module=ALL-UNNAMED \ --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED \ --add-exports java.base/jdk.internal.access=ALL-UNNAMED diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java index b6ef5ab8487..26cdf4473cf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -39,10 +39,7 @@ * /test/lib * @run main/othervm/native * -agentlib:resexhausted=-waittime=5 - * -Xms64m - * -Xmx64m - * -XX:MaxMetaspaceSize=9m - * -XX:-UseGCOverheadLimit + * -XX:MaxMetaspaceSize=20m * nsk.jvmti.ResourceExhausted.resexhausted003 */ diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index e9d7c769523..6a2ab0d1e04 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -583,8 +583,6 @@ java/net/Socket/asyncClose/Race.java 8317801 aix-ppc6 # jdk_nio -java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64 - java/nio/channels/Channels/SocketChannelStreams.java 8317838 aix-ppc64 java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all diff --git a/test/jdk/com/sun/jdi/ClassUnloadEventTest.java b/test/jdk/com/sun/jdi/ClassUnloadEventTest.java index cf77ba846ae..41b1bff5e42 100644 --- a/test/jdk/com/sun/jdi/ClassUnloadEventTest.java +++ b/test/jdk/com/sun/jdi/ClassUnloadEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,18 +24,13 @@ /* * @test * @bug 8256811 - * @modules java.base/jdk.internal.org.objectweb.asm - * java.base/jdk.internal.misc + * @modules java.base/jdk.internal.misc * @library /test/lib * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native ClassUnloadEventTest run */ -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; import jdk.test.lib.classloader.ClassUnloadCommon; import com.sun.jdi.*; @@ -45,6 +40,9 @@ import java.util.*; import java.io.*; +import java.lang.classfile.ClassFile; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; public class ClassUnloadEventTest { static final String CLASS_NAME_PREFIX = "SampleClass__"; @@ -65,18 +63,13 @@ public static void main(String[] args) throws Exception { } } - private static class TestClassLoader extends ClassLoader implements Opcodes { + private static class TestClassLoader extends ClassLoader { private static byte[] generateSampleClass(String name) { - ClassWriter cw = new ClassWriter(0); - - cw.visit(52, ACC_SUPER | ACC_PUBLIC, name, null, "java/lang/Object", null); - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null); - mv.visitCode(); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - cw.visitEnd(); - return cw.toByteArray(); + return ClassFile.of().build(ClassDesc.of(name), clb -> + clb.withVersion(52, 0) + .withFlags(ClassFile.ACC_SUPER | ClassFile.ACC_PUBLIC) + .withMethodBody("m", ConstantDescs.MTD_void, ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC, cob -> + cob.return_())); } @Override diff --git a/test/jdk/com/sun/net/httpserver/bugs/B6361557.java b/test/jdk/com/sun/net/httpserver/bugs/B6361557.java index 57e831ec693..66094230d69 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/B6361557.java +++ b/test/jdk/com/sun/net/httpserver/bugs/B6361557.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -65,7 +65,7 @@ public void handle (HttpExchange t) } final static String request = "GET /test/foo.html HTTP/1.1\r\nContent-length: 0\r\n\r\n"; - final static ByteBuffer requestBuf = ByteBuffer.allocate(64).put(request.getBytes()); + final static ByteBuffer requestBuf = ByteBuffer.wrap(request.getBytes()); public static void main (String[] args) throws Exception { Handler handler = new Handler(); diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index a77f97018ca..3a5d1ef7c97 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, 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 @@ -260,6 +260,7 @@ public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws T try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena); assertTrue(segment.isMapped()); + assertTrue(segment.toString().contains("mapped")); arena.close(); mappedBufferOp.apply(segment); } diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index a76bc69fbd8..af639596734 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, 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 @@ -234,8 +234,10 @@ public void testToString(Supplier segmentSupplier) { assertTrue(s.contains("byteSize: ")); if (segment.heapBase().isPresent()) { assertTrue(s.contains("heapBase: [")); + assertFalse(s.contains("native")); } else { assertFalse(s.contains("heapBase: ")); + assertTrue(s.contains("native")); } assertFalse(s.contains("Optional")); } diff --git a/test/jdk/java/io/File/GetXSpace.java b/test/jdk/java/io/File/GetXSpace.java index d76000dbef5..512ea51780b 100644 --- a/test/jdk/java/io/File/GetXSpace.java +++ b/test/jdk/java/io/File/GetXSpace.java @@ -54,6 +54,8 @@ public class GetXSpace { System.loadLibrary("GetXSpace"); } + private static final Pattern DF_PATTERN = Pattern.compile("([^\\s]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+\\d+%\\s+([^\\s].*)\n"); + private static int fail = 0; private static int pass = 0; private static Throwable first; @@ -104,8 +106,17 @@ private static class Space { Space(String name) { this.name = name; long[] sizes = new long[4]; - if (getSpace0(name, sizes)) - System.err.println("WARNING: total space is estimated"); + if (Platform.isWindows() & isCDDrive(name)) { + try { + getCDDriveSpace(name, sizes); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("can't get CDDrive sizes"); + } + } else { + if (getSpace0(name, sizes)) + System.err.println("WARNING: total space is estimated"); + } this.size = sizes[0]; this.total = sizes[1]; this.free = sizes[2]; @@ -167,7 +178,8 @@ private static void compare(Space s) { out.format("%s (%d):%n", s.name(), s.size()); String fmt = " %-4s total = %12d free = %12d usable = %12d%n"; - out.format(fmt, "getSpace0", s.total(), s.free(), s.available()); + String method = Platform.isWindows() & isCDDrive(s.name()) ? "getCDDriveSpace" : "getSpace0"; + out.format(fmt, method, s.total(), s.free(), s.available()); out.format(fmt, "getXSpace", ts, fs, us); // If the file system can dynamically change size, this check will fail. @@ -324,7 +336,7 @@ private static int testFile(Path dir) { private static int testVolumes() { out.println("--- Testing volumes"); // Find all of the partitions on the machine and verify that the sizes - // returned by File::getXSpace are equivalent to those from getSpace0 + // returned by File::getXSpace are equivalent to those from getSpace0 or getCDDriveSpace ArrayList l; try { l = paths(); @@ -397,4 +409,40 @@ public static void main(String[] args) throws Exception { // size[3] usable space: number of bytes available to the caller // private static native boolean getSpace0(String root, long[] space); + + private static native boolean isCDDrive(String root); + + private static void getCDDriveSpace(String root, long[] sizes) + throws IOException { + String[] cmd = new String[] {"df", "-k", "-P", root}; + Process p = Runtime.getRuntime().exec(cmd); + StringBuilder sb = new StringBuilder(); + + try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) { + String s; + int i = 0; + while ((s = in.readLine()) != null) { + // skip header + if (i++ == 0) continue; + sb.append(s).append("\n"); + } + } + out.println(sb); + + Matcher m = DF_PATTERN.matcher(sb); + int j = 0; + while (j < sb.length()) { + if (m.find(j)) { + sizes[0] = Long.parseLong(m.group(2)) * 1024; + sizes[1] = Long.parseLong(m.group(3)) * 1024; + sizes[2] = sizes[0] - sizes[1]; + sizes[3] = Long.parseLong(m.group(4)) * 1024; + j = m.end(); + } else { + throw new RuntimeException("unrecognized df output format: " + + "charAt(" + j + ") = '" + + sb.charAt(j) + "'"); + } + } + } } diff --git a/test/jdk/java/io/File/libGetXSpace.c b/test/jdk/java/io/File/libGetXSpace.c index a4e36bd2431..c45aea14691 100644 --- a/test/jdk/java/io/File/libGetXSpace.c +++ b/test/jdk/java/io/File/libGetXSpace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,6 +159,33 @@ Java_GetXSpace_getSpace0 (*env)->SetLongArrayRegion(env, sizes, 0, 4, array); return totalSpaceIsEstimated; } + +JNIEXPORT jboolean JNICALL +Java_GetXSpace_isCDDrive + (JNIEnv *env, jclass cls, jstring root) +{ +#ifdef WINDOWS + const jchar* strchars = (*env)->GetStringChars(env, root, NULL); + if (strchars == NULL) { + JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException", + "GetStringChars"); + return JNI_FALSE; + } + + LPCWSTR path = (LPCWSTR)strchars; + UINT driveType = GetDriveTypeW(path); + + (*env)->ReleaseStringChars(env, root, strchars); + + if (driveType != DRIVE_CDROM) { + return JNI_FALSE; + } + + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} #ifdef __cplusplus } #endif diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 8add9e76104..aee1b19a01d 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -40,6 +40,7 @@ import jdk.internal.util.OperatingSystem; import jdk.internal.util.OSVersion; +import jdk.internal.util.StaticProperty; /** * Uses Files.probeContentType to probe html file, custom file type, and minimal @@ -83,7 +84,7 @@ private static int checkContentTypes(String expected, String actual) { if (!expected.equals(actual)) { if (!OperatingSystem.isWindows()) { Path userMimeTypes = - Path.of(System.getProperty("user.home"), ".mime.types"); + Path.of(StaticProperty.userHome(), ".mime.types"); checkMimeTypesFile(userMimeTypes); Path etcMimeTypes = Path.of("/etc/mime.types"); @@ -188,9 +189,10 @@ public static void main(String[] args) throws IOException { exTypes.add(new ExType("xlsx", List.of("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))); exTypes.add(new ExType("wasm", List.of("application/wasm"))); - // extensions with content type that differs on Windows 11+ + // extensions with content type that differs on Windows 11+ and + // Windows Server 2025 if (OperatingSystem.isWindows() && - (System.getProperty("os.name").endsWith("11") || + (StaticProperty.osName().matches("^.*[11|2025]$") || new OSVersion(10, 0).compareTo(OSVersion.current()) > 0)) { System.out.println("Windows 11+ detected: using different types"); exTypes.add(new ExType("bz2", List.of("application/bz2", "application/x-bzip2", "application/x-bzip", "application/x-compressed"))); diff --git a/test/jdk/sun/util/calendar/zi/DayOfWeek.java b/test/jdk/java/nio/file/spi/CustomSystemClassLoader.java similarity index 64% rename from test/jdk/sun/util/calendar/zi/DayOfWeek.java rename to test/jdk/java/nio/file/spi/CustomSystemClassLoader.java index ed820a83c39..8ad9a41c5fd 100644 --- a/test/jdk/sun/util/calendar/zi/DayOfWeek.java +++ b/test/jdk/java/nio/file/spi/CustomSystemClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,32 +21,20 @@ * questions. */ +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; + /** - * Day of week enum. - * - * @since 1.6 + * Use by tests in SetDefaultProvider to test startup with a custom default file system + * provider and a custom system class loader. */ -enum DayOfWeek { - SUNDAY("Sun"), - MONDAY("Mon"), - TUESDAY("Tue"), - WEDNESDAY("Wed"), - THURSDAY("Thu"), - FRIDAY("Fri"), - SATURDAY("Sat"); - - private final String abbr; - - private DayOfWeek(String abbr) { - this.abbr = abbr; - } - - String getAbbr() { - return abbr; - } +public class CustomSystemClassLoader extends ClassLoader { + public CustomSystemClassLoader(ClassLoader parent) { + super(parent); - int value() { - return ordinal() + 1; + // use default file system + FileSystem fs = FileSystems.getDefault(); + var path = fs.getPath("foo"); } -} +} \ No newline at end of file diff --git a/test/jdk/java/nio/file/spi/SetDefaultProvider.java b/test/jdk/java/nio/file/spi/SetDefaultProvider.java index ea154b5952e..f4486885b6a 100644 --- a/test/jdk/java/nio/file/spi/SetDefaultProvider.java +++ b/test/jdk/java/nio/file/spi/SetDefaultProvider.java @@ -23,10 +23,10 @@ /* * @test - * @bug 4313887 7006126 8142968 8178380 8183320 8210112 8266345 8263940 8331467 + * @bug 4313887 7006126 8142968 8178380 8183320 8210112 8266345 8263940 8331467 8346573 * @modules jdk.jartool jdk.jlink * @library /test/lib - * @build testfsp/* testapp/* + * @build testfsp/* testapp/* CustomSystemClassLoader * @run junit SetDefaultProvider * @summary Runs tests with -Djava.nio.file.spi.DefaultFileSystemProvider set on * the command line to override the default file system provider @@ -204,6 +204,19 @@ void testPatchedAppOnModulePath2() throws Exception { "-m", TESTAPP + "/" + TESTAPP_MAIN); } + /** + * Test file system provider on class path in conjunction with a custom system + * class loader that uses the file system API during its initialization. + */ + @Test + void testCustomSystemClassLoader() throws Exception { + String testClasses = System.getProperty("test.classes"); + exec(SET_DEFAULT_FSP, + "-Djava.system.class.loader=CustomSystemClassLoader", + "-cp", ofClasspath(testClasses, TESTFSP_CLASSES, TESTAPP_CLASSES), + TESTAPP_MAIN); + } + /** * Returns the directory containing the classes for the given module. */ diff --git a/test/jdk/java/util/TimeZone/tools/share/Makefile b/test/jdk/java/util/TimeZone/tools/share/Makefile index 69c4838efe0..47734b96c55 100644 --- a/test/jdk/java/util/TimeZone/tools/share/Makefile +++ b/test/jdk/java/util/TimeZone/tools/share/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 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,8 +33,7 @@ TZDATA = ../../../../../../../src/java.base/share/data/tzdata TZDATA_VER = `grep '^tzdata' $(TZDATA)/VERSION` TZNAME = africa antarctica asia australasia europe northamerica \ - solar87 solar88 solar89 southamerica \ - backward + southamerica backward TZFILES = $(addprefix $(TZDATA)/, $(TZNAME)) ALIASLIST = aliases.txt DISPLAYNAMES = displaynames.txt diff --git a/test/jdk/javax/print/attribute/PageRangesException.java b/test/jdk/javax/print/attribute/PageRangesException.java new file mode 100644 index 00000000000..81f9eb1a592 --- /dev/null +++ b/test/jdk/javax/print/attribute/PageRangesException.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2001, 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. + */ + +import javax.print.attribute.standard.PageRanges; + +/* + * @test + * @bug 4433126 4433096 + * @key printer + * @summary The line "ERROR: " should NOT appear. + * @run main PageRangesException + */ + +public class PageRangesException { + public static void main(String[] args) throws Exception { + // test 4433126 + try { + PageRanges pr = new PageRanges("0:22"); + throw new RuntimeException("ERROR: no exceptions"); + } catch (IllegalArgumentException ie) { + System.out.println("OKAY: IllegalArgumentException " + ie); + } + + // test 4433096 + try { + int[][] m = null; + PageRanges pr = new PageRanges(m); + throw new RuntimeException("ERROR: NullPointerException expected"); + } catch (IllegalArgumentException ie) { + throw new RuntimeException("ERROR: IllegalArgumentException", ie); + } catch (NullPointerException e) { + System.out.println("OKAY: NullPointerException"); + } + } +} diff --git a/test/jdk/javax/swing/JOptionPane/bug4174551.java b/test/jdk/javax/swing/JOptionPane/bug4174551.java index f65f95192b7..dbe6cdffe1a 100644 --- a/test/jdk/javax/swing/JOptionPane/bug4174551.java +++ b/test/jdk/javax/swing/JOptionPane/bug4174551.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4174551 + * @bug 4174551 8346260 * @summary JOptionPane should allow custom buttons * @library /java/awt/regtesthelpers * @build PassFailJFrame diff --git a/test/jdk/jdk/classfile/SnippetsTest.java b/test/jdk/jdk/classfile/SnippetsTest.java index f6fa2281e14..2b84820e9b9 100644 --- a/test/jdk/jdk/classfile/SnippetsTest.java +++ b/test/jdk/jdk/classfile/SnippetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -42,7 +42,9 @@ public class SnippetsTest { @ParameterizedTest @ValueSource(strings = { "src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java", - "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java"}) + "src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java", + "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java" + }) void testSnippet(String source) throws Exception { var p = Paths.get(System.getProperty("test.src", ".")).toAbsolutePath(); while ((p = p.getParent()) != null) { diff --git a/test/jdk/jdk/classfile/TEST.properties b/test/jdk/jdk/classfile/TEST.properties index 62414b36eae..2d8d20cf1f4 100644 --- a/test/jdk/jdk/classfile/TEST.properties +++ b/test/jdk/jdk/classfile/TEST.properties @@ -2,6 +2,4 @@ maxOutputSize = 2500000 modules = \ java.base/jdk.internal.classfile.components \ java.base/jdk.internal.classfile.impl \ - java.base/jdk.internal.classfile.impl.verifier \ - java.base/jdk.internal.org.objectweb.asm \ - java.base/jdk.internal.org.objectweb.asm.tree \ No newline at end of file + java.base/jdk.internal.classfile.impl.verifier \ No newline at end of file diff --git a/test/jdk/jdk/classfile/helpers/Transforms.java b/test/jdk/jdk/classfile/helpers/Transforms.java index b0e88bd8212..dba3f21cbd8 100644 --- a/test/jdk/jdk/classfile/helpers/Transforms.java +++ b/test/jdk/jdk/classfile/helpers/Transforms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -43,27 +43,12 @@ import java.lang.classfile.MethodModel; import java.lang.classfile.MethodTransform; import jdk.internal.classfile.components.ClassRemapper; -import jdk.internal.org.objectweb.asm.AnnotationVisitor; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.FieldVisitor; -import jdk.internal.org.objectweb.asm.Handle; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.ModuleVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.RecordComponentVisitor; -import jdk.internal.org.objectweb.asm.TypePath; -import jdk.internal.org.objectweb.asm.tree.ClassNode; /** * Transforms */ public class Transforms { - static int ASM9 = 9 << 16 | 0 << 8; - public static final ClassTransform threeLevelNoop = (cb, ce) -> { if (ce instanceof MethodModel mm) { cb.transformMethod(mm, (mb, me) -> { @@ -128,42 +113,10 @@ public enum NoOpTransform { UNSHARED_3(false, threeLevelNoop), SHARED_3_NO_STACKMAP(true, threeLevelNoop, ClassFile.StackMapsOption.DROP_STACK_MAPS), SHARED_3_NO_DEBUG(true, threeLevelNoop, ClassFile.DebugElementsOption.DROP_DEBUG, ClassFile.LineNumbersOption.DROP_LINE_NUMBERS), - ASM_1(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - return cw.toByteArray(); - }), - ASM_UNSHARED_1(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - return cw.toByteArray(); - }), - ASM_3(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new CustomClassVisitor(cw), 0); - return cw.toByteArray(); - }), - ASM_UNSHARED_3(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new CustomClassVisitor(cw), 0); - return cw.toByteArray(); - }), - ASM_TREE(bytes -> { - ClassNode node = new ClassNode(); - ClassReader cr = new ClassReader(bytes); - cr.accept(node, 0); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - node.accept(cw); - return cw.toByteArray(); - }), CLASS_REMAPPER(bytes -> ClassRemapper.of(Map.of()).remapClass(ClassFile.of(), ClassFile.of().parse(bytes))); - // Need ASM, LOW_UNSHARED + // Need LOW_UNSHARED public final UnaryOperator transform; public final boolean shared; @@ -202,12 +155,6 @@ public Optional classRecord(byte[] bytes) throws IOException { } public enum InjectNopTransform { - ASM_NOP_SHARED(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new NopClassVisitor(cw), 0); - return cw.toByteArray(); - }), NOP_SHARED(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -242,13 +189,6 @@ public void accept(CodeElement e) { } public enum SimpleTransform { - ASM_ADD_FIELD(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - cw.visitField(0, "argleBargleWoogaWooga", "I", null, null); - return cw.toByteArray(); - }), HIGH_SHARED_ADD_FIELD(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -273,20 +213,6 @@ public void atEnd(ClassBuilder builder) { cb.withField("argleBargleWoogaWooga", ConstantDescs.CD_int, b -> { }); }); }), - ASM_DEL_METHOD(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - ClassVisitor v = new ClassVisitor(ASM9, cw) { - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - return (name.equals("hashCode") && descriptor.equals("()Z")) - ? null - : super.visitMethod(access, name, descriptor, signature, exceptions); - } - }; - cr.accept(cw, 0); - return cw.toByteArray(); - }), HIGH_SHARED_DEL_METHOD(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -319,277 +245,4 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str } } - static class CustomClassVisitor extends ClassVisitor { - - public CustomClassVisitor(ClassVisitor writer) { - super(ASM9, writer); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public void visitSource(String source, String debug) { - super.visitSource(source, debug); - } - - @Override - public ModuleVisitor visitModule(String name, int access, String version) { - return super.visitModule(name, access, version); - } - - @Override - public void visitNestHost(String nestHost) { - super.visitNestHost(nestHost); - } - - @Override - public void visitOuterClass(String owner, String name, String descriptor) { - super.visitOuterClass(owner, name, descriptor); - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - return super.visitAnnotation(descriptor, visible); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitAttribute(Attribute attribute) { - super.visitAttribute(attribute); - } - - @Override - public void visitNestMember(String nestMember) { - super.visitNestMember(nestMember); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { - return super.visitRecordComponent(name, descriptor, signature); - } - - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - return super.visitField(access, name, descriptor, signature, value); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - return new CustomMethodVisitor(mv); - } - - @Override - public void visitEnd() { - super.visitEnd(); - } - }; - - - static class CustomMethodVisitor extends MethodVisitor { - - public CustomMethodVisitor(MethodVisitor methodVisitor) { - super(ASM9, methodVisitor); - } - - @Override - public void visitParameter(String name, int access) { - super.visitParameter(name, access); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - return super.visitAnnotationDefault(); - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - return super.visitAnnotation(descriptor, visible); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitAnnotableParameterCount(int parameterCount, boolean visible) { - super.visitAnnotableParameterCount(parameterCount, visible); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) { - return super.visitParameterAnnotation(parameter, descriptor, visible); - } - - @Override - public void visitAttribute(Attribute attribute) { - super.visitAttribute(attribute); - } - - @Override - public void visitCode() { - super.visitCode(); - } - - @Override - public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { - super.visitFrame(type, numLocal, local, numStack, stack); - } - - @Override - public void visitInsn(int opcode) { - super.visitInsn(opcode); - } - - @Override - public void visitIntInsn(int opcode, int operand) { - super.visitIntInsn(opcode, operand); - } - - @Override - public void visitVarInsn(int opcode, int var) { - super.visitVarInsn(opcode, var); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - super.visitTypeInsn(opcode, type); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { - super.visitFieldInsn(opcode, owner, name, descriptor); - } - - @Override - @SuppressWarnings("deprecation") - public void visitMethodInsn(int opcode, String owner, String name, String descriptor) { - super.visitMethodInsn(opcode, owner, name, descriptor); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { - super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); - } - - @Override - public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { - super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - super.visitJumpInsn(opcode, label); - } - - @Override - public void visitLabel(Label label) { - super.visitLabel(label); - } - - @Override - public void visitLdcInsn(Object value) { - super.visitLdcInsn(value); - } - - @Override - public void visitIincInsn(int var, int increment) { - super.visitIincInsn(var, increment); - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { - super.visitTableSwitchInsn(min, max, dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - super.visitLookupSwitchInsn(dflt, keys, labels); - } - - @Override - public void visitMultiANewArrayInsn(String descriptor, int numDimensions) { - super.visitMultiANewArrayInsn(descriptor, numDimensions); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - super.visitTryCatchBlock(start, end, handler, type); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { - super.visitLocalVariable(name, descriptor, signature, start, end, index); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) { - return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); - } - - @Override - public void visitLineNumber(int line, Label start) { - super.visitLineNumber(line, start); - } - - @Override - public void visitMaxs(int maxStack, int maxLocals) { - super.visitMaxs(maxStack, maxLocals); - } - - @Override - public void visitEnd() { - super.visitEnd(); - } - }; - - static class NopClassVisitor extends CustomClassVisitor { - - public NopClassVisitor(ClassVisitor writer) { - super(writer); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - return new NopMethodVisitor(mv); - } - } - - static class NopMethodVisitor extends CustomMethodVisitor { - - public NopMethodVisitor(MethodVisitor methodVisitor) { - super(methodVisitor); - } - - @Override - public void visitCode() { - super.visitCode(); - visitInsn(Opcodes.NOP); - } - } - } diff --git a/test/jdk/sun/util/calendar/zi/BackEnd.java b/test/jdk/sun/util/calendar/zi/BackEnd.java deleted file mode 100644 index 10d71ff7210..00000000000 --- a/test/jdk/sun/util/calendar/zi/BackEnd.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * BackEnd is an abstract base class for a back-end of compiling - * Olson's zoneinfo database and generating Java zoneinfo database. - * - * @since 1.4 - */ -abstract class BackEnd { - - /** - * Receives each zone's TimeZone information which was created by - * {@link Zoneinfo#parse} in class Zoneinfo, - * and processes it. - * - * @param tz Timezone object for each zone - * @return 0 if no error occurred, otherwise 1. - */ - abstract int processZoneinfo(Timezone tz); - - /** - * Receives whole information which is generated by JavaZic's front-end - * in the form of Mapping object and generates all Java zone information - * files. - * - * @param m Mappings object which is generated by - * {@link Main#compile() Main.compile()}. - * @return 0 if no error occurred, otherwise 1. - */ - abstract int generateSrc(Mappings m); - - /** - * Decides which backend class should be used and returns its instance. - * @return an instance of backend class - */ - static BackEnd getBackEnd() { - if (Zoneinfo.isYearForTimeZoneDataSpecified) { - return new Simple(); - } else if (Main.outputDoc) { - return new GenDoc(); - } else { - return new Gen(); - } - } -} diff --git a/test/jdk/sun/util/calendar/zi/Beyond2037.java b/test/jdk/sun/util/calendar/zi/Beyond2037.java deleted file mode 100644 index af6f16067a8..00000000000 --- a/test/jdk/sun/util/calendar/zi/Beyond2037.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8073446 8262110 - * @summary Tests DST related beyond the year 2037 - * @run testng Beyond2037 - */ - -import java.text.SimpleDateFormat; -import java.util.TimeZone; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; - -@Test -public class Beyond2037 { - - @DataProvider - Object[][] dstTransition() { - return new Object[][] { - {"2037/03/08 01:59:59:999", "2037/03/08 01:59:59:999"}, - {"2037/03/08 02:00:00:000", "2037/03/08 03:00:00:000"}, - {"2038/03/14 01:59:59:999", "2038/03/14 01:59:59:999"}, - {"2038/03/14 02:00:00:000", "2038/03/14 03:00:00:000"}, - {"2099/03/08 01:59:59:999", "2099/03/08 01:59:59:999"}, - {"2099/03/08 02:00:00:000", "2099/03/08 03:00:00:000"}, - {"2100/03/14 01:59:59:999", "2100/03/14 01:59:59:999"}, - {"2100/03/14 02:00:00:000", "2100/03/14 03:00:00:000"}, - {"8000/03/12 01:59:59:999", "8000/03/12 01:59:59:999"}, - {"8000/03/12 02:00:00:000", "8000/03/12 03:00:00:000"}, - }; - } - - @Test(dataProvider="dstTransition") - public void testDstTransition(String source, String expected) throws Exception { - var timeZone = TimeZone.getTimeZone("America/New_York"); - var sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS" ); - sdf.setTimeZone(timeZone); - assertEquals(sdf.format(sdf.parse(source)), expected); - } - - @Test - public void testGetOffset() throws Exception { - var timeZone = TimeZone.getTimeZone("PST8PDT"); - var df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - df.setTimeZone(timeZone); - var tMilli = df.parse("7681-03-09 03:20:49").getTime(); - assertEquals(timeZone.getOffset(tMilli), -25200000); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Checksum.java b/test/jdk/sun/util/calendar/zi/Checksum.java deleted file mode 100644 index 93a1c827903..00000000000 --- a/test/jdk/sun/util/calendar/zi/Checksum.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.zip.CRC32; - -/** - * Checksum provides methods for calculating a CRC32 value for a - * transitions table. - * - * @since 1.4 - */ -public class Checksum extends CRC32 -{ - /** - * Updates the CRC32 value from each byte of the given int - * value. The bytes are used in the big endian order. - * @param val the int value - */ - public void update(int val) { - byte[] b = new byte[4]; - b[0] = (byte)((val >>> 24) & 0xff); - b[1] = (byte)((val >>> 16) & 0xff); - b[2] = (byte)((val >>> 8) & 0xff); - b[3] = (byte)(val & 0xff); - update(b); - } - - /** - * Updates the CRC32 value from each byte of the given long - * value. The bytes are used in the big endian order. - * @param val the long value - */ - void update(long val) { - byte[] b = new byte[8]; - b[0] = (byte)((val >>> 56) & 0xff); - b[1] = (byte)((val >>> 48) & 0xff); - b[2] = (byte)((val >>> 40) & 0xff); - b[3] = (byte)((val >>> 32) & 0xff); - b[4] = (byte)((val >>> 24) & 0xff); - b[5] = (byte)((val >>> 16) & 0xff); - b[6] = (byte)((val >>> 8) & 0xff); - b[7] = (byte)(val & 0xff); - update(b); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Gen.java b/test/jdk/sun/util/calendar/zi/Gen.java deleted file mode 100644 index 4cdabc55321..00000000000 --- a/test/jdk/sun/util/calendar/zi/Gen.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.RandomAccessFile; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Gen is one of back-end classes of javazic, and generates - * ZoneInfoMappings and zone-specific file for each zone. - */ -class Gen extends BackEnd { - - /** - * Generates datafile in binary TLV format for each time zone. - * Regarding contents of output files, see {@link ZoneInfoFile}. - * - * @param Timezone - * @return 0 if no errors, or 1 if error occurred. - */ - int processZoneinfo(Timezone tz) { - try { - int size; - String outputDir = Main.getOutputDir(); - String zonefile = ZoneInfoFile.getFileName(tz.getName()); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - - /* If zonefile includes file-separator, it's treated as part of - * pathname. And make directory if necessary. - */ - int index = zonefile.lastIndexOf(File.separatorChar); - if (index != -1) { - outputDir += zonefile.substring(0, index+1); - } - File outD = new File(outputDir); - outD.mkdirs(); - - FileOutputStream fos = - new FileOutputStream(outputDir + zonefile.substring(index+1)); - DataOutputStream dos = new DataOutputStream(fos); - - /* Output Label */ - dos.write(ZoneInfoFile.JAVAZI_LABEL, 0, - ZoneInfoFile.JAVAZI_LABEL.length); - - /* Output Version of ZoneInfoFile */ - dos.writeByte(ZoneInfoFile.JAVAZI_VERSION); - - List transitions = tz.getTransitions(); - if (transitions != null) { - List dstOffsets = tz.getDstOffsets(); - List offsets = tz.getOffsets(); - - if ((dstOffsets == null && offsets != null) || - (dstOffsets != null && offsets == null)) { - Main.panic("Data not exist. (dstOffsets or offsets)"); - return 1; - } - - /* Output Transition records */ - dos.writeByte(ZoneInfoFile.TAG_Transition); - size = transitions.size(); - dos.writeShort((size * 8) & 0xFFFF); - int dstoffset; - for (int i = 0; i < size; i++) { - /* if DST offset is 0, this means DST isn't used. - * (NOT: offset's index is 0.) - */ - if ((dstoffset = dstOffsets.get(i).intValue()) == -1) { - dstoffset = 0; - } - - dos.writeLong((transitions.get(i).longValue() << 12) - | (dstoffset << 4) - | offsets.get(i).intValue()); - - } - - /* Output data for GMTOffset */ - List gmtoffset = tz.getGmtOffsets(); - dos.writeByte(ZoneInfoFile.TAG_Offset); - size = gmtoffset.size(); - dos.writeShort((size * 4) & 0xFFFF); - for (int i = 0; i < size; i++) { - dos.writeInt(gmtoffset.get(i)); - } - } - - /* Output data for SimpleTimeZone */ - List stz = tz.getLastRules(); - if (stz != null) { - RuleRec[] rr = new RuleRec[2]; - boolean wall = true; - - rr[0] = stz.get(0); - rr[1] = stz.get(1); - - dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone); - wall = rr[0].getTime().isWall() && rr[1].getTime().isWall(); - if (wall) { - dos.writeShort(32); - } else { - dos.writeShort(40); - } - - for (int i = 0; i < 2; i++) { - dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number - dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone()); - dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt()); - dos.writeInt((int)rr[i].getTime().getTime()); - if (!wall) { - dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1); - } - } - } - - /* Output RawOffset */ - dos.writeByte(ZoneInfoFile.TAG_RawOffset); - dos.writeShort(4); - dos.writeInt(tz.getRawOffset()); - - /* Output willGMTOffsetChange flag */ - if (tz.willGMTOffsetChange()) { - dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange); - dos.writeShort(1); - dos.writeByte(1); - } - - /* Output LastDSTSaving */ - dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving); - dos.writeShort(2); - dos.writeShort(tz.getLastDSTSaving()/1000); - - /* Output checksum */ - dos.writeByte(ZoneInfoFile.TAG_CRC32); - dos.writeShort(4); - dos.writeInt(tz.getCRC32()); - - fos.close(); - dos.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - /** - * Generates ZoneInfoMappings in binary TLV format for each zone. - * Regarding contents of output files, see {@link ZoneInfoFile}. - * - * @param Mappings - * @return 0 if no errors, or 1 if error occurred. - */ - int generateSrc(Mappings map) { - try { - int index; - int block_size; - int roi_size; - long fp; - String outputDir = Main.getOutputDir(); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - - File outD = new File(outputDir); - outD.mkdirs(); - - /* Open ZoneInfoMapping file to write. */ - RandomAccessFile raf = - new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw"); - - /* Whether rawOffsetIndex list exists or not. */ - List roi = map.getRawOffsetsIndex(); - if (roi == null) { - Main.panic("Data not exist. (rawOffsetsIndex)"); - return 1; - } - roi_size = roi.size(); - - /* Whether rawOffsetIndexTable list exists or not. */ - List> roit = map.getRawOffsetsIndexTable(); - if (roit == null || roit.size() != roi_size) { - Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size"); - return 1; - } - - /* Output Label */ - raf.write(ZoneInfoFile.JAVAZM_LABEL, 0, - ZoneInfoFile.JAVAZM_LABEL.length); - - /* Output Version */ - raf.writeByte(ZoneInfoFile.JAVAZM_VERSION); - - index = ZoneInfoFile.JAVAZM_LABEL.length + 2; - - /* Output Version of Olson's tzdata */ - byte[] b = Main.getVersionName().getBytes("UTF-8"); - raf.writeByte(ZoneInfoFile.TAG_TZDataVersion); - raf.writeShort((b.length+1) & 0xFFFF); - raf.write(b); - raf.writeByte(0x00); - index += b.length + 4; - - /* Output ID list. */ - raf.writeByte(ZoneInfoFile.TAG_ZoneIDs); - block_size = 2; - raf.writeShort(block_size & 0xFFFF); - short nID = 0; - raf.writeShort(nID & 0xFFFF); - for (int i = 0; i < roi_size; i++) { - for (String key : roit.get(i)) { - byte size = (byte)key.getBytes("UTF-8").length; - raf.writeByte(size & 0xFF); - raf.write(key.getBytes("UTF-8"), 0, size); - block_size += 1 + size; - nID++; - } - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.writeShort(nID & 0xFFFF); - raf.seek(fp); - - /* Output sorted rawOffset list. */ - raf.writeByte(ZoneInfoFile.TAG_RawOffsets); - index += 3 + block_size; - block_size = roi_size * 4; - raf.writeShort(block_size & 0xFFFF); - for (int i = 0; i < roi_size; i++) { - raf.writeInt(Integer.parseInt(roi.get(i).toString())); - } - - /* Output sorted rawOffsetIndex list. */ - raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices); - index += 3 + block_size; - block_size = 0; - raf.writeShort(block_size & 0xFFFF); - int num; - for (int i = 0; i < roi_size; i++) { - num = roit.get(i).size(); - block_size += num; - for (int j = 0; j < num; j++) { - raf.writeByte(i); - } - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.seek(fp); - - /* Whether alias list exists or not. */ - Map a = map.getAliases(); - if (a == null) { - Main.panic("Data not exist. (aliases)"); - return 0; - } - - /* Output ID list. */ - raf.writeByte(ZoneInfoFile.TAG_ZoneAliases); - index += 3 + block_size; - block_size = 2; - raf.writeShort(block_size & 0xFFFF); - raf.writeShort(a.size() & 0xFFFF); - for (String key : a.keySet()) { - String alias = a.get(key); - byte key_size = (byte)key.length(); - byte alias_size = (byte)alias.length(); - raf.writeByte(key_size & 0xFF); - raf.write(key.getBytes("UTF-8"), 0, key_size); - raf.writeByte(alias_size & 0xFF); - raf.write(alias.getBytes("UTF-8"), 0, alias_size); - block_size += 2 + key_size + alias_size; - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.seek(fp); - - /* Output the exclude list if it exists. */ - List excludedZones = map.getExcludeList(); - if (excludedZones != null) { - raf.writeByte(ZoneInfoFile.TAG_ExcludedZones); - index += 3 + block_size; - block_size = 2; - raf.writeShort(block_size & 0xFFFF); // place holder - raf.writeShort(excludedZones.size()); // the number of excluded zones - for (String name : excludedZones) { - byte size = (byte) name.length(); - raf.writeByte(size); // byte length - raf.write(name.getBytes("UTF-8"), 0, size); // zone name - block_size += 1 + size; - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort(block_size & 0xFFFF); - raf.seek(fp); - } - - /* Close ZoneInfoMapping file. */ - raf.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } -} diff --git a/test/jdk/sun/util/calendar/zi/GenDoc.java b/test/jdk/sun/util/calendar/zi/GenDoc.java deleted file mode 100644 index e9e6ebc0cd8..00000000000 --- a/test/jdk/sun/util/calendar/zi/GenDoc.java +++ /dev/null @@ -1,776 +0,0 @@ -/* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.StringTokenizer; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * GenDoc is one of back-end classes of javazic, and generates - * index.html and other html files which prints the detailed time zone - * information for each zone. - */ -class GenDoc extends BackEnd { - - private static final String docDir = "doc"; - - private static final String header1 = - "\n" + - "\n\n\n\n" + - "Java Platform, Standard Edition - TimeZone information based on "; - private static final String header3 = - "-->\n<TITLE>\n" + - "Java Platform, Standard Edition TimeZone - "; - private static final String header4 = - "\n" + - "\n\n"; - - private static final String body1 = - "\n"; - private static final String body2 = - "\n"; - - private static final String footer = - "\n"; - - - // list of time zone name and zonefile name/real time zone name - // e.g. - // key (String) : value (String) - // "America/Denver" : "America/Denver.html" (real time zone) - // "America/Shiprock" : "America/Denver" (alias) - TreeMap timezoneList = new TreeMap(); - - // list of time zone's display name and time zone name - // e.g. - // key (String) : value (String) - // "Tokyo, Asia" : "Asia/Tokyo" - // "Marengo, Indiana, America" : "America/Indiana/Marengo" - // (aliases included) - TreeMap displayNameList = new TreeMap(); - - // list of top level regions - // e.g. - // key (String) : value (String) - // "America" : "America.html" - // (including entries in America/Indiana/, America/Kentucky/, ...) - TreeMap regionList = new TreeMap(); - - // mapping list from zone name to latitude & longitude - // This list is generated from zone.tab. - // e.g. - // key (String) : value (LatitudeAndLongitude object) - // "Asia/Tokyo" : latitude=35.3916, longitude=13.9444 - // (aliases not included) - HashMap mapList = null; - - // SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT - // offset will change in the future, its last known offset is - // used. - SortedMap> zonesByOffset = new TreeMap>(); - - /** - * Generates HTML document for each zone. - * @param Timezone - * @return 0 if no errors, or 1 if error occurred. - */ - int processZoneinfo(Timezone tz) { - try { - int size; - int index; - String outputDir = Main.getOutputDir(); - String zonename = tz.getName(); - String zonefile = ZoneInfoFile.getFileName(zonename) + ".html"; - List stz = tz.getLastRules(); - timezoneList.put(zonename, zonefile); - displayNameList.put(transform(zonename), zonename); - - // Populate zonesByOffset. (Zones that will change their - // GMT offsets are also added to zonesByOffset here.) - int lastKnownOffset = tz.getRawOffset(); - Set set = zonesByOffset.get(lastKnownOffset); - if (set == null) { - set = new TreeSet(); - zonesByOffset.put(lastKnownOffset, set); - } - set.add(zonename); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - outputDir += docDir + File.separatorChar; - - index = zonename.indexOf('/'); - if (index != -1) { - regionList.put(zonename.substring(0, index), - zonename.substring(0, index) + ".html"); - } - - /* If zonefile includes file-separator, it's treated as part of - * pathname. And make directory if necessary. - */ - index = zonefile.lastIndexOf('/'); - if (index != -1) { - zonefile.replace('/', File.separatorChar); - outputDir += zonefile.substring(0, index+1); - } - File outD = new File(outputDir); - outD.mkdirs(); - - /* If mapfile is available, add a link to the appropriate map */ - if (mapList == null && Main.getMapFile() != null) { - mapList = new HashMap(); - FileReader fr = new FileReader(Main.getMapFile()); - BufferedReader in = new BufferedReader(fr); - String line; - while ((line = in.readLine()) != null) { - // skip blank and comment lines - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - StringTokenizer tokens = new StringTokenizer(line); - String token = tokens.nextToken(); /* We don't use the first token. */ - token = tokens.nextToken(); - LatitudeAndLongitude location = new LatitudeAndLongitude(token); - token = tokens.nextToken(); - mapList.put(token, location); - } - in.close(); - } - - /* Open zoneinfo file to write. */ - FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1)); - BufferedWriter out = new BufferedWriter(fw); - - out.write(header1 + new Date() + header3 + zonename + header4); - out.write(body1 + "" + zonename + ""); - LatitudeAndLongitude location = (mapList != null ? mapList.get(zonename) : null); - if (location != null) { - int deg, min, sec; - - deg = location.getLatDeg(); - min = location.getLatMin(); - sec = location.getLatSec(); - if (deg < 0) { - min = -min; - sec = -sec; - } else if (min < 0) { - sec = -sec; - } - out.write("   " + - "[map]"); - } - out.write("\n

    \n"); - - List zone = tz.getZones(); - List rule = tz.getRules(); - if (rule != null && zone != null) { - out.write("\n" + - "\n" + - "\n" + - "\n" + - "\n

    " + - "Rules
    " + - "
    Zone
    \n"); - } - - /* Output Rule records. */ - if (rule != null) { - size = rule.size(); - out.write("

    \n" + - "Rules\n" + - "\n" + - "\n" + - "" + - "" + - "\n\n"); - for (int i = 0; i < size; i++) { - out.write("\n"); - StringTokenizer st = new StringTokenizer(rule.get(i).getLine()); - String s; - if (st.hasMoreTokens()) { /* RULE - truncated */ - st.nextToken(); - } - if (st.hasMoreTokens()) { /* NAME */ - out.write(""); - } - if (st.hasMoreTokens()) { /* FROM */ - out.write(""); - } - if (st.hasMoreTokens()) { /* TO */ - s = st.nextToken(); - if (s.equals("min") || s.equals("max")) { - out.write(""); - } else { - out.write(""); - } - } - if (st.hasMoreTokens()) { /* TYPE */ - out.write(""); - } - if (st.hasMoreTokens()) { /* IN */ - out.write(""); - } - if (st.hasMoreTokens()) { /* ON */ - out.write(""); - } - if (st.hasMoreTokens()) { /* AT */ - out.write(""); - } - if (st.hasMoreTokens()) { /* SAVE */ - out.write(""); - } - if (st.hasMoreTokens()) { /* LETTER/S */ - out.write(""); - } - if (st.hasMoreTokens()) { /* NOTES */ - s = st.nextToken(); - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - index = s.indexOf('#'); - out.write("\n"); - } else { - out.write("\n"); - } - out.write("\n"); - } - out.write("
    NAMEFROMTOTYPEINONATSAVELETTER/SNOTES
    " + st.nextToken() + "" + st.nextToken() + "" + s + "" + s + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + s.substring(index+1) + " 
    \n

     

    \n"); - } - - /* Output Zone records. */ - if (zone != null) { - size = zone.size(); - out.write("

    \n" + - "Zone\n" + - "\n" + - "\n" + - "" + - "\n\n"); - for (int i = 0; i < size; i++) { - out.write("\n"); - StringTokenizer st = new StringTokenizer(zone.get(i).getLine()); - String s = st.nextToken(); - if (s.equals("Zone")) { /* NAME */ - s = st.nextToken(); - s = st.nextToken(); - } - out.write(""); /* GMTOFFSET */ - if (st.hasMoreTokens()) { /* RULES */ - out.write(""); - } - if (st.hasMoreTokens()) { /* FORMAT */ - s = st.nextToken(); - index = s.indexOf('#'); - if (index != -1) { - if (index != 0) { - out.write(""); /* FORMAT */ - s = s.substring(index+1); - } else { - out.write(""); /* FORMAT */ - } - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - out.write(""); /* UNTIL */ - out.write("\n\n"); /* NOTES */ - continue; - } else { - out.write(""); /* FORMAT */ - } - } - - if (st.hasMoreTokens()) { /* UNTIL */ - s = st.nextToken(); - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - index = s.indexOf('#'); - if (index != -1) { - if (index != 0) { - out.write(""); /* UNTIL */ - } else { - out.write(""); /* UNTIL */ - } - out.write("\n"); /* NOTES */ - } else { - out.write(""); /* UNTIL */ - out.write("\n"); /* NOTES */ - } - } else { - out.write(""); /* UNTIL */ - out.write("\n"); /* NOTES */ - } - out.write("\n"); - } - out.write("
    GMTOFFRULESFORMATUNTILNOTES
    " + s + "" + st.nextToken() + "" + s.substring(0, index-1) + - "  " + s + "
    " + s + "" + s.substring(0, index-1) + - " " + s.substring(index+1) + - "" + s + "   
    \n"); - } - out.write(body2 + footer); - - out.close(); - fw.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - /** - * Generates index.html and other top-level frame files. - * @param Mappings - * @return 0 if no errors, or 1 if error occurred. - */ - int generateSrc(Mappings map) { - try { - int len; - Object o[]; - String outputDir = Main.getOutputDir(); - FileWriter fw1, fw2; - BufferedWriter out1, out2; - - /* Whether alias list exists or not. */ - Map a = map.getAliases(); - if (a == null) { - Main.panic("Data not exist. (aliases)"); - return 1; - } - - timezoneList.putAll(a); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - outputDir += docDir + File.separatorChar; - - File outD = new File(outputDir); - outD.mkdirs(); - - /* Creates index.html */ - fw1 = new FileWriter(outputDir + "index.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + - "\n" + - "\n" + - "\n" + - "\n" + - "" + - "\n" + - "\n" + - "\n" + - "<H2>\nFrame Alert\n</H2>\n\n" + - "<P>\n\n" + - "This document is designed to be viewed using the frames feature. If you see this\n" + - "message, you are using a non-frame-capable web client.\n" + - "<BR>\n" + - "Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" + - "\n" + footer); - - out1.close(); - fw1.close(); - - - /* Creates overview-frame.html */ - fw1 = new FileWriter(outputDir + "overview-frame.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "\n\n" + - "\n" + - "\n
    \n" + - "JavaTM Platform
    Standard Ed.
    \n\n" + - "\n\n\n
    " + - "

    \n\nAll Time Zones Sorted By:\n
    \n" + - "  GMT offsets\n
    \n" + - "  Zone names\n
    " + - "  City names\n" + - "

    \n\nContinents and Oceans\n
    \n"); - - for (String regionKey : regionList.keySet()) { - out1.write("  " + regionKey + - "
    \n"); - - fw2 = new FileWriter(outputDir + regionList.get(regionKey), - false); - out2 = new BufferedWriter(fw2); - - out2.write(header1 + new Date() + header3 + regionKey + - header4 + body1 + "" + - regionKey + "\n
    \n\n\n\n\n
    "); - - boolean found = false; - for (String timezoneKey : timezoneList.keySet()) { - int regionIndex = timezoneKey.indexOf('/'); - if (regionIndex == -1 || - !regionKey.equals(timezoneKey.substring(0, regionIndex))) { - if (found) { - break; - } else { - continue; - } - } - - found = true; - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out2.write(timezoneKey + - " (alias for " + "" + - realName + ")"); - } else { - out2.write("" + timezoneKey + - ""); - } - out2.write("
    \n"); - } - out2.write("
    \n" + body2 + footer); - - out2.close(); - fw2.close(); - } - out1.write("

    \n" + body2 + footer); - - out1.close(); - fw1.close(); - - - /* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "Sorted by GMT offsets\n" + - "
    \n\n" + "\n" + - "\n\n\n\n\n"); - } - } - out1.write("\n\n
    \n"); - - List roi = map.getRawOffsetsIndex(); - List> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (Integer offset : zonesByOffset.keySet()) { - int off = roi.get(index); - Set perRO = zonesByOffset.get(offset); - if (offset == off) { - // Merge aliases into zonesByOffset - perRO.addAll(roit.get(index)); - } - index++; - - for (String timezoneKey : perRO) { - out1.write("
    (" + - Time.toGMTFormat(offset.toString()) + - ")"); - - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(timezoneKey + - " (alias for " + "" + realName + - ")"); - } else { - out1.write("" + timezoneKey + - ""); - } - out1.write("
    \n" + body2 + footer); - - out1.close(); - fw1.close(); - - - /* Creates allTimeZone-frame2.html (Sorted by zone names) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "Sorted by zone names\n" + - "
    \n\n" + "\n" + - "\n\n\n
    \n"); - o = timezoneList.keySet().toArray(); - len = timezoneList.size(); - for (int i = 0; i < len; i++) { - Object timezoneKey = o[i]; - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(timezoneKey + - " (alias for " + - "" + realName + - ")"); - } else { - out1.write("" + timezoneKey + - ""); - } - out1.write("
    \n"); - } - out1.write("
    \n" + body2 + footer); - - out1.close(); - fw1.close(); - - /* Creates allTimeZone-frame3.html (Sorted by city names) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "Sorted by city names\n" + - "
    \n\n" + "\n" + - "\n\n\n
    \n"); - - Set aliasSet = a.keySet(); - len = aliasSet.size(); - String aliasNames[] = aliasSet.toArray(new String[0]); - for (int i = 0; i < len; i++) { - displayNameList.put(transform(aliasNames[i]), - aliasNames[i]); - } - - o = displayNameList.keySet().toArray(); - len = displayNameList.size(); - for (int i = 0; i < len; i++) { - Object displayName = o[i]; - Object timezoneKey = displayNameList.get(o[i]); - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(displayName + - " (alias for " + - "" + realName + - ")"); - } else { - out1.write("" + displayName + - ""); - } - out1.write("
    \n"); - } - - out1.write("
    \n" + body2 + footer); - - out1.close(); - fw1.close(); - - /* Creates overview-summary.html */ - fw1 = new FileWriter(outputDir + "overview-summary.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "

    This is the list of time zones generated from " + - Main.getVersionName() + " for Java Platform, " + - "Standard Edition. The source code can be obtained " + - "from ftp site " + - "ftp://elsie.nci.nih.gov/pub/. A total of " + - len + - " time zones and aliases are supported " + - "in this edition. For the " + - "format of rules and zones, refer to the zic " + - "(zoneinfo compiler) man page on " + - "Solaris or Linux.

    \n" + - "

    Note that the time zone data is not " + - "a public interface of the Java Platform. No " + - "applications should rely on the time zone data of " + - "this document. Time zone names and data " + - "may change without any prior notice.

    \n" + - body2 + footer); - - out1.close(); - fw1.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - String transform(String s) { - int index = s.lastIndexOf("/"); - - /* If the string doesn't include any delimiter, return */ - if (index == -1) { - return s; - } - - int lastIndex = index; - String str = s.substring(index+1); - do { - index = s.substring(0, lastIndex).lastIndexOf('/'); - str += ", " + s.substring(index+1, lastIndex); - lastIndex = index; - } while (index > -1); - - return str; - } - - static class LatitudeAndLongitude { - - private int latDeg, latMin, latSec, longDeg, longMin, longSec; - - LatitudeAndLongitude(String s) { - try { - // First of all, check the string has the correct format: - // either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS - - if (!s.startsWith("+") && !s.startsWith("-")) { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - int index; - if (((index = s.lastIndexOf("+")) <= 0) && - ((index = s.lastIndexOf("-")) <= 0)) { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - - if (index == 5) { - latDeg = Integer.parseInt(s.substring(1, 3)); - latMin = Integer.parseInt(s.substring(3, 5)); - latSec = 0; - } else if (index == 7) { - latDeg = Integer.parseInt(s.substring(1, 3)); - latMin = Integer.parseInt(s.substring(3, 5)); - latSec = Integer.parseInt(s.substring(5, 7)); - } else { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - if (s.startsWith("-")){ - latDeg = -latDeg; - latMin = -latMin; - latSec = -latSec; - } - - int len = s.length(); - if (index == 5 && len == 11) { - longDeg = Integer.parseInt(s.substring(index+1, index+4)); - longMin = Integer.parseInt(s.substring(index+4, index+6)); - longSec = 0; - } else if (index == 7 && len == 15) { - longDeg = Integer.parseInt(s.substring(index+1, index+4)); - longMin = Integer.parseInt(s.substring(index+4, index+6)); - longSec = Integer.parseInt(s.substring(index+6, index+8)); - } else { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - if (s.charAt(index) == '-'){ - longDeg = -longDeg; - longMin = -longMin; - longSec = -longSec; - } - } catch(Exception e) { - Main.warning("LatitudeAndLongitude() Parse error: " + s); - } - } - - int getLatDeg() { - return latDeg; - } - - int getLatMin() { - return latMin; - } - - int getLatSec() { - return latSec; - } - - int getLongDeg() { - return longDeg; - } - - int getLongMin() { - return longMin; - } - - int getLongSec() { - return longSec; - } - } -} diff --git a/test/jdk/sun/util/calendar/zi/Main.java b/test/jdk/sun/util/calendar/zi/Main.java deleted file mode 100644 index 8078d7e2425..00000000000 --- a/test/jdk/sun/util/calendar/zi/Main.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.ArrayList; -import java.util.List; - -/** - * Main class for the javazic time zone data compiler. - * - * @since 1.4 - */ -public class Main { - - private static boolean verbose = false; - static boolean outputDoc = false; - - private List ziFiles = new ArrayList(); - private static String zoneNamesFile = null; - private static String versionName = "unknown"; - private static String outputDir = "zoneinfo"; - private static String mapFile = null; - - /** - * Parses the specified arguments and sets up the variables. - * @param argv the arguments - */ - void processArgs(String[] argv) { - for (int i = 0; i < argv.length; i++) { - String arg = argv[i]; - if (arg.startsWith("-h")) { - usage(); - System.exit(0); - } else if (arg.equals("-d")) { - outputDir = argv[++i]; - } else if (arg.equals("-v")) { - verbose = true; - } else if (arg.equals("-V")) { - versionName = argv[++i]; - } else if (arg.equals("-doc")) { - outputDoc = true; - } else if (arg.equals("-map")) { - outputDoc = true; - mapFile = argv[++i]; - } else if (arg.equals("-f")) { - zoneNamesFile = argv[++i]; - } else if (arg.equals("-S")) { - try { - Zoneinfo.setYear(Integer.parseInt(argv[++i])); - } catch (Exception e) { - error("invalid year: " + argv[i]); - usage(); - System.exit(1); - } - } else { - boolean isStartYear = arg.equals("-s"); - if (isStartYear || arg.equals("-e")) { - try { - int year = Integer.parseInt(argv[++i]); - if (isStartYear) { - Zoneinfo.setStartYear(year); - } else { - Zoneinfo.setEndYear(year); - } - } catch (Exception e) { - error("invalid year: " + argv[i]); - usage(); - System.exit(1); - } - } else { - // the rest of args are zoneinfo source files - while (i < argv.length) { - ziFiles.add(argv[i++]); - } - } - } - } - } - - /** - * Parses zoneinfo source files - */ - int compile() { - int nFiles = ziFiles.size(); - int status = 0; - Mappings maps = new Mappings(); - BackEnd backend = BackEnd.getBackEnd(); - - for (int i = 0; i < nFiles; i++) { - Zoneinfo frontend = Zoneinfo.parse(ziFiles.get(i)); - - for (String key : frontend.getZones().keySet()) { - info(key); - - Timezone tz = frontend.phase2(key); - status |= backend.processZoneinfo(tz); - } - - maps.add(frontend); - } - - // special code for dealing with the conflicting name "MET" - Zone.addMET(); - - maps.resolve(); - - status |= backend.generateSrc(maps); - - return status; - } - - public static void main(String[] argv) { - Main zic = new Main(); - - /* - * Parse args - */ - zic.processArgs(argv); - - /* - * Read target zone names - */ - if (zoneNamesFile != null) { - Zone.readZoneNames(zoneNamesFile); - } - - zic.compile(); - } - - void usage() { - System.err.println("Usage: javazic [options] file...\n"+ - " -f namefile file containing zone names\n"+ - " to be generated (ie, generating subset)\n"+ - " -d dir output directory\n"+ - " -v verbose\n"+ - " -V datavers specifies the tzdata version string\n"+ - " (eg, \"tzdata2000g\")"+ - " -S year output only SimleTimeZone data of that year\n"+ - " -s year start year (default: 1900)\n"+ - " -e year end year (default: 2037)\n"+ - " -doc generates HTML documents\n"+ - " -map mapfile generates HTML documents with map information\n"+ - " file... zoneinfo source file(s)"); - } - - /** - * @return the output directory path name - */ - static String getOutputDir() { - return outputDir; - } - - /** - * @return the map file's path and name - */ - static String getMapFile() { - return mapFile; - } - - /** - * Returns the time zone data version string specified by the -V - * option. If it is not specified, "unknown" is returned. - * @return the time zone data version string - */ - static String getVersionName() { - return versionName; - } - - /** - * Prints out the specified fatal error message and calls {@link - * java.lang.System#exit System.exit(1)}. - * @param msg the fatal error message - */ - static void panic(String msg) { - printMessage("fatal error", msg); - System.exit(1); - } - - /** - * Prints out the specified error message. - * @param msg the error message - */ - static void error(String msg) { - printMessage("error", msg); - } - - /** - * Prints out the specified warning message. - * @param msg the warning message - */ - static void warning(String msg) { - printMessage("warning", msg); - } - - /** - * Prints out the informative message. - * @param msg the informative message - */ - static void info(String msg) { - if (verbose) { - printMessage(null, msg); - } - } - - private static void printMessage(String type, String msg) { - if (type != null) { - type += ": "; - } else { - type = ""; - } - System.err.println("javazic: " + type + msg); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Mappings.java b/test/jdk/sun/util/calendar/zi/Mappings.java deleted file mode 100644 index 582a9509a51..00000000000 --- a/test/jdk/sun/util/calendar/zi/Mappings.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * Mappings generates two Maps and a List which are used by - * javazic BackEnd. - * - * @since 1.4 - */ -class Mappings { - // All aliases specified by Link statements. It's alias name to - // real name mappings. - private Map aliases; - - private List rawOffsetsIndex; - - private List> rawOffsetsIndexTable; - - // Zone names to be excluded from rawOffset table. Those have GMT - // offsets to change some future time. - private List excludeList; - - /** - * Constructor creates some necessary instances. - */ - Mappings() { - aliases = new TreeMap(); - rawOffsetsIndex = new LinkedList(); - rawOffsetsIndexTable = new LinkedList>(); - } - - /** - * Generates aliases and rawOffsets tables. - * @param zi a Zoneinfo containing Zones - */ - void add(Zoneinfo zi) { - Map zones = zi.getZones(); - - for (String zoneName : zones.keySet()) { - Zone zone = zones.get(zoneName); - String zonename = zone.getName(); - int rawOffset = zone.get(zone.size()-1).getGmtOffset(); - - // If the GMT offset of this Zone will change in some - // future time, this Zone is added to the exclude list. - boolean isExcluded = false; - for (int i = 0; i < zone.size(); i++) { - ZoneRec zrec = zone.get(i); - if ((zrec.getGmtOffset() != rawOffset) - && (zrec.getUntilTime(0) > Time.getCurrentTime())) { - if (excludeList == null) { - excludeList = new ArrayList(); - } - excludeList.add(zone.getName()); - isExcluded = true; - break; - } - } - - if (!rawOffsetsIndex.contains(new Integer(rawOffset))) { - // Find the index to insert this raw offset zones - int n = rawOffsetsIndex.size(); - int i; - for (i = 0; i < n; i++) { - if (rawOffsetsIndex.get(i) > rawOffset) { - break; - } - } - rawOffsetsIndex.add(i, rawOffset); - - Set perRawOffset = new TreeSet(); - if (!isExcluded) { - perRawOffset.add(zonename); - } - rawOffsetsIndexTable.add(i, perRawOffset); - } else if (!isExcluded) { - int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); - Set perRawOffset = rawOffsetsIndexTable.get(i); - perRawOffset.add(zonename); - } - } - - Map a = zi.getAliases(); - // If there are time zone names which refer to any of the - // excluded zones, add those names to the excluded list. - if (excludeList != null) { - for (String zoneName : a.keySet()) { - String realname = a.get(zoneName); - if (excludeList.contains(realname)) { - excludeList.add(zoneName); - } - } - } - aliases.putAll(a); - } - - /** - * Adds valid aliases to one of per-RawOffset table and removes - * invalid aliases from aliases List. Aliases referring to - * excluded zones are not added to a per-RawOffset table. - */ - void resolve() { - int index = rawOffsetsIndexTable.size(); - List toBeRemoved = new ArrayList(); - for (String key : aliases.keySet()) { - boolean validname = false; - for (int j = 0; j < index; j++) { - Set perRO = rawOffsetsIndexTable.get(j); - boolean isExcluded = (excludeList == null) ? - false : excludeList.contains(key); - - if ((perRO.contains(aliases.get(key)) || isExcluded) - && Zone.isTargetZone(key)) { - validname = true; - if (!isExcluded) { - perRO.add(key); - Main.info("Alias <"+key+"> added to the list."); - } - break; - } - } - - if (!validname) { - Main.info("Alias <"+key+"> removed from the list."); - toBeRemoved.add(key); - } - } - - // Remove zones, if any, from the list. - for (String key : toBeRemoved) { - aliases.remove(key); - } - // Eliminate any alias-to-alias mappings. For example, if - // there are A->B and B->C, A->B is changed to A->C. - Map newMap = new HashMap(); - for (String key : aliases.keySet()) { - String realid = aliases.get(key); - String leaf = realid; - while (aliases.get(leaf) != null) { - leaf = aliases.get(leaf); - } - if (!realid.equals(leaf)) { - newMap.put(key, leaf); - } - } - aliases.putAll(newMap); - } - - Map getAliases() { - return(aliases); - } - - List getRawOffsetsIndex() { - return(rawOffsetsIndex); - } - - List> getRawOffsetsIndexTable() { - return(rawOffsetsIndexTable); - } - - List getExcludeList() { - return excludeList; - } -} diff --git a/test/jdk/sun/util/calendar/zi/Month.java b/test/jdk/sun/util/calendar/zi/Month.java deleted file mode 100644 index bab909f7637..00000000000 --- a/test/jdk/sun/util/calendar/zi/Month.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * Month enum handles month related manipulation. - * - * @since 1.4 - */ -enum Month { - JANUARY("Jan"), - FEBRUARY("Feb"), - MARCH("Mar"), - APRIL("Apr"), - MAY("May"), - JUNE("Jun"), - JULY("Jul"), - AUGUST("Aug"), - SEPTEMBER("Sep"), - OCTOBER("Oct"), - NOVEMBER("Nov"), - DECEMBER("Dec"); - - private final String abbr; - - private Month(String abbr) { - this.abbr = abbr; - } - - int value() { - return ordinal() + 1; - } - - /** - * Parses the specified string as a month abbreviation. - * @param name the month abbreviation - * @return the Month value - */ - static Month parse(String name) { - int len = name.length(); - - if (name.regionMatches(true, 0, "January", 0, len)) return Month.JANUARY; - if (name.regionMatches(true, 0, "February", 0, len)) return Month.FEBRUARY; - if (name.regionMatches(true, 0, "March", 0, len)) return Month.MARCH; - if (name.regionMatches(true, 0, "April", 0, len)) return Month.APRIL; - if (name.regionMatches(true, 0, "May", 0, len)) return Month.MAY; - if (name.regionMatches(true, 0, "June", 0, len)) return Month.JUNE; - if (name.regionMatches(true, 0, "July", 0, len)) return Month.JULY; - if (name.regionMatches(true, 0, "August", 0, len)) return Month.AUGUST; - if (name.regionMatches(true, 0, "September", 0, len)) return Month.SEPTEMBER; - if (name.regionMatches(true, 0, "October", 0, len)) return Month.OCTOBER; - if (name.regionMatches(true, 0, "November", 0, len)) return Month.NOVEMBER; - if (name.regionMatches(true, 0, "December", 0, len)) return Month.DECEMBER; - - throw new IllegalArgumentException("Unknown month: " + name); - } - - /** - * @param month the nunmth number (1-based) - * @return the month name in uppercase of the specified month - */ - static String toString(int month) { - if (month >= JANUARY.value() && month <= DECEMBER.value()) { - return "Calendar." + Month.values()[month - 1]; - } - throw new IllegalArgumentException("wrong month number: " + month); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Rule.java b/test/jdk/sun/util/calendar/zi/Rule.java deleted file mode 100644 index 3098dc7e766..00000000000 --- a/test/jdk/sun/util/calendar/zi/Rule.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.StringTokenizer; - -/** - * Rule manipulates Rule records. - * - * @since 1.4 - */ -class Rule { - - private List list; - private String name; - - /** - * Constructs a Rule which consists of a Rule record list. The - * specified name is given to this Rule. - * @param name the Rule name - */ - Rule(String name) { - this.name = name; - list = new ArrayList(); - } - - /** - * Added a RuleRec to the Rule record list. - */ - void add(RuleRec rec) { - list.add(rec); - } - - /** - * @return the Rule name - */ - String getName() { - return name; - } - - /** - * Gets all rule records that cover the given year. - * - * @param year the year number for which the rule is applicable. - * @return rules in List that are collated in time. If no rule is found, an empty - * List is returned. - */ - List getRules(int year) { - List rules = new ArrayList(3); - for (RuleRec rec : list) { - if (year >= rec.getFromYear() && year <= rec.getToYear()) { - if ((rec.isOdd() && year % 2 == 0) || (rec.isEven() && year % 2 == 1)) - continue; - rules.add(rec); - } - } - int n = rules.size(); - if (n <= 1) { - return rules; - } - if (n == 2) { - RuleRec rec1 = rules.get(0); - RuleRec rec2 = rules.get(1); - if (rec1.getMonthNum() > rec2.getMonthNum()) { - rules.set(0, rec2); - rules.set(1, rec1); - } else if (rec1.getMonthNum() == rec2.getMonthNum()) { - // TODO: it's not accurate to ignore time types (STD, WALL, UTC) - long t1 = Time.getLocalTime(year, rec1.getMonth(), - rec1.getDay(), rec1.getTime().getTime()); - long t2 = Time.getLocalTime(year, rec2.getMonth(), - rec2.getDay(), rec2.getTime().getTime()); - if (t1 > t2) { - rules.set(0, rec2); - rules.set(1, rec1); - } - } - return rules; - } - - final int y = year; - RuleRec[] recs = new RuleRec[rules.size()]; - rules.toArray(recs); - - Arrays.sort(recs, new Comparator() { - public int compare(RuleRec r1, RuleRec r2) { - int n = r1.getMonthNum() - r2.getMonthNum(); - if (n != 0) { - return n; - } - // TODO: it's not accurate to ignore time types (STD, WALL, UTC) - long t1 = Time.getLocalTime(y, r1.getMonth(), - r1.getDay(), r1.getTime().getTime()); - long t2 = Time.getLocalTime(y, r2.getMonth(), - r2.getDay(), r2.getTime().getTime()); - return Long.compare(t1, t2); - } - public boolean equals(Object o) { - return this == o; - } - }); - rules.clear(); - for (int i = 0; i < n; i++) { - if (i != 0 && recs[i -1].getSave() == recs[i].getSave()) { - // we have two recs back to back with same saving for the same year. - if (recs[i].isLastRule()) { - continue; - } else if (recs[i - 1].isLastRule()) { - rules.remove(rules.size() - 1); - } - } - rules.add(recs[i]); - } - return rules; - } - - /** - * Gets rule records that have either "max" or cover the endYear - * value in its DST schedule. - * - * @return rules that contain last DST schedule. An empty - * ArrayList is returned if no last rules are found. - */ - List getLastRules() { - RuleRec start = null; - RuleRec end = null; - - for (int i = 0; i < list.size(); i++) { - RuleRec rec = list.get(i); - if (rec.isLastRule()) { - if (rec.getSave() > 0) { - start = rec; - } else { - end = rec; - } - } - } - if (start == null || end == null) { - int endYear = Zoneinfo.getEndYear(); - for (int i = 0; i < list.size(); i++) { - RuleRec rec = list.get(i); - if (endYear >= rec.getFromYear() && endYear <= rec.getToYear()) { - if (start == null && rec.getSave() > 0) { - start = rec; - } else { - if (end == null && rec.getSave() == 0) { - end = rec; - } - } - } - } - } - - List r = new ArrayList(2); - if (start == null || end == null) { - if (start != null || end != null) { - Main.warning("found last rules for "+name+" inconsistent."); - } - return r; - } - - r.add(start); - r.add(end); - return r; - } -} diff --git a/test/jdk/sun/util/calendar/zi/RuleDay.java b/test/jdk/sun/util/calendar/zi/RuleDay.java deleted file mode 100644 index 9cd81c1e524..00000000000 --- a/test/jdk/sun/util/calendar/zi/RuleDay.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * RuleDay class represents the value of the "ON" field. The day of - * week values start from 1 following the {@link java.util.Calendar} - * convention. - * - * @since 1.4 - */ -class RuleDay { - private String dayName = null; - private DayOfWeek dow; - private boolean lastOne = false; - private int soonerOrLater = 0; - private int thanDayOfMonth; // day of month (e.g., 8 for "Sun>=8") - - RuleDay() { - } - - RuleDay(int day) { - thanDayOfMonth = day; - } - - int getDay() { - return thanDayOfMonth; - } - - /** - * @return the day of week value (1-based) - */ - int getDayOfWeekNum() { - return dow.value(); - } - - /** - * @return true if this rule day represents the last day of - * week. (e.g., lastSun). - */ - boolean isLast() { - return lastOne; - } - - /** - * @return true if this rule day represents the day of week on or - * later than (after) the {@link #getDay}. (e.g., Sun>=1) - */ - boolean isLater() { - return soonerOrLater > 0; - } - - /** - * @return true if this rule day represents the day of week on or - * earlier than (before) the {@link #getDay}. (e.g., Sun<=15) - */ - boolean isEarlier() { - return soonerOrLater < 0; - } - - /** - * @return true if this rule day represents an exact day. - */ - boolean isExact() { - return soonerOrLater == 0; - } - - /** - * Parses the "ON" field and constructs a RuleDay. - * @param day an "ON" field string (e.g., "Sun>=1") - * @return a RuleDay representing the given "ON" field - */ - static RuleDay parse(String day) { - RuleDay d = new RuleDay(); - if (day.startsWith("last")) { - d.lastOne = true; - d.dayName = day.substring(4); - d.dow = getDOW(d.dayName); - } else { - int index; - if ((index = day.indexOf(">=")) != -1) { - d.dayName = day.substring(0, index); - d.dow = getDOW(d.dayName); - d.soonerOrLater = 1; // greater or equal - d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); - } else if ((index = day.indexOf("<=")) != -1) { - d.dayName = day.substring(0, index); - d.dow = getDOW(d.dayName); - d.soonerOrLater = -1; // less or equal - d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); - } else { - // it should be an integer value. - d.thanDayOfMonth = Integer.parseInt(day); - } - } - return d; - } - - /** - * Converts this RuleDay to the SimpleTimeZone day rule. - * @return the converted SimpleTimeZone day rule - */ - int getDayForSimpleTimeZone() { - if (isLast()) { - return -1; - } - return isEarlier() ? -getDay() : getDay(); - } - - /** - * Converts this RuleDay to the SimpleTimeZone day-of-week rule. - * @return the SimpleTimeZone day-of-week rule value - */ - int getDayOfWeekForSimpleTimeZoneInt() { - if (isEarlier() || isLater()) { - return -getDayOfWeekNum(); - } - return isLast() ? getDayOfWeekNum() : 0; - } - - /** - * @return the string representation of the {@link - * #getDayOfWeekForSimpleTimeZoneInt} value - */ - String getDayOfWeekForSimpleTimeZone() { - int d = getDayOfWeekForSimpleTimeZoneInt(); - if (d == 0) { - return "0"; - } - String sign = ""; - if (d < 0) { - sign = "-"; - d = -d; - } - return sign + toString(d); - } - - private static DayOfWeek getDOW(String name) { - int len = name.length(); - - if (name.regionMatches(true, 0, "Monday", 0, len)) return DayOfWeek.MONDAY; - if (name.regionMatches(true, 0, "Tuesday", 0, len)) return DayOfWeek.TUESDAY; - if (name.regionMatches(true, 0, "Wednesday", 0, len)) return DayOfWeek.WEDNESDAY; - if (name.regionMatches(true, 0, "Thursday", 0, len)) return DayOfWeek.THURSDAY; - if (name.regionMatches(true, 0, "Friday", 0, len)) return DayOfWeek.FRIDAY; - if (name.regionMatches(true, 0, "Saturday", 0, len)) return DayOfWeek.SATURDAY; - if (name.regionMatches(true, 0, "Sunday", 0, len)) return DayOfWeek.SUNDAY; - - throw new IllegalArgumentException("Unknown day-of-week: " + name); - } - - /** - * Converts the specified day of week value to the day-of-week - * name defined in {@link java.util.Calendar}. - * @param dow 1-based day of week value - * @return the Calendar day of week name with "Calendar." prefix. - * @throws IllegalArgumentException if the specified dow value is out of range. - */ - static String toString(int dow) { - if (dow >= DayOfWeek.SUNDAY.value() && dow <= DayOfWeek.SATURDAY.value()) { - return "Calendar." + DayOfWeek.values()[dow - 1]; - } - throw new IllegalArgumentException("wrong Day_of_Week number: " + dow); - } -} diff --git a/test/jdk/sun/util/calendar/zi/RuleRec.java b/test/jdk/sun/util/calendar/zi/RuleRec.java deleted file mode 100644 index e6e18773d16..00000000000 --- a/test/jdk/sun/util/calendar/zi/RuleRec.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.StringTokenizer; - -/** - * RuleRec class represents one record of the Rule set. - * - * @since 1.4 - */ -class RuleRec { - private int fromYear; - private int toYear; - private String type; - private Month inMonth; - private RuleDay onDay; - private Time atTime; - private int save; - private String letters; - private String line; - private boolean isLastRule; - - int getFromYear() { - return fromYear; - } - - int getToYear() { - return toYear; - } - - Month getMonth() { - return inMonth; - } - - int getMonthNum() { - return inMonth.value(); - } - - RuleDay getDay() { - return onDay; - } - - Time getTime() { - return atTime; - } - - int getSave() { - return save; - } - - String getLine() { - return line; - } - - /** - * Sets the line from the text file. - * @param line the text of the line - */ - void setLine(String line) { - this.line = line; - } - - /** - * @return true if the rule type is "odd". - */ - boolean isOdd() { - return "odd".equals(type); - } - - /** - * @return true if the rule type is "even". - */ - boolean isEven() { - return "even".equals(type); - } - - /** - * Determines if this rule record is the last DST schedule rule. - * - * @return true if this rule record has "max" as TO (year). - */ - boolean isLastRule() { - return isLastRule; - } - - /** - * Determines if the unadjusted until time of the specified ZoneRec - * is the same as the transition time of this rule in the same - * year as the ZoneRec until year. - * - * @param zrec ZoneRec to compare to - * @param save the amount of daylight saving in milliseconds - * @param gmtOffset the GMT offset value in milliseconds - * @return true if the unadjusted until time is the same as rule's - * transition time. - */ - boolean isSameTransition(ZoneRec zrec, int save, int gmtOffset) { - long until, transition; - - if (zrec.getUntilTime().getType() != atTime.getType()) { - until = zrec.getLocalUntilTime(save, gmtOffset); - transition = Time.getLocalTime(zrec.getUntilYear(), - getMonth(), - getDay(), - save, - gmtOffset, - atTime); - } else { - until = zrec.getLocalUntilTime(); - transition = Time.getLocalTime(zrec.getUntilYear(), - getMonth(), - getDay(), - atTime.getTime()); - } - - return until == transition; - } - - /** - * Parses a Rule line and returns a RuleRec object. - * - * @param tokens a StringTokenizer object that should contain a - * token for the "FROM" field and the rest. - * @return a RuleRec object. - */ - static RuleRec parse(StringTokenizer tokens) { - RuleRec rec = new RuleRec(); - try { - // FROM - String token = tokens.nextToken(); - try { - rec.fromYear = Integer.parseInt(token); - } catch (NumberFormatException e) { - // it's not integer - if ("min".equals(token) || "minimum".equals(token)) { - rec.fromYear = Zoneinfo.getMinYear(); - } else if ("max".equals(token) || "maximum".equals(token)) { - rec.fromYear = Zoneinfo.getMaxYear(); - } else { - Main.panic("invalid year value: "+token); - } - } - - // TO - token = tokens.nextToken(); - rec.isLastRule = false; - try { - rec.toYear = Integer.parseInt(token); - } catch (NumberFormatException e) { - // it's not integer - int len = token.length(); - if (token.regionMatches(true, 0, "minimum", 0, len)) { - rec.fromYear = Zoneinfo.getMinYear(); - } else if (token.regionMatches(true, 0, "maximum", 0, len)) { - rec.toYear = Integer.MAX_VALUE; - rec.isLastRule = true; - } else if (token.regionMatches(true, 0, "only", 0, len)) { - rec.toYear = rec.fromYear; - } else { - Main.panic("invalid year value: "+token); - } - } - - // TYPE - rec.type = tokens.nextToken(); - - // IN - rec.inMonth = Month.parse(tokens.nextToken()); - - // ON - rec.onDay = RuleDay.parse(tokens.nextToken()); - - // AT - rec.atTime = Time.parse(tokens.nextToken()); - - // SAVE - rec.save = (int) Time.parse(tokens.nextToken()).getTime(); - - // LETTER/S - rec.letters = tokens.nextToken(); - } catch (Exception e) { - e.printStackTrace(); - } - return rec; - } - - /** - * Calculates the transition time of the given year under this rule. - * @param year the year value - * @param gmtOffset the GMT offset value in milliseconds - * @param save the amount of daylight save time - * @return the transition time in milliseconds of the given year in UTC. - */ - long getTransitionTime(int year, int gmtOffset, int save) { - long time = Time.getLocalTime(year, getMonth(), - getDay(), atTime.getTime()); - if (atTime.isSTD()) { - time -= gmtOffset; - } else if (atTime.isWall()) { - time -= gmtOffset + save; - } - return time; - } - - private static int getInt(StringTokenizer tokens) { - String token = tokens.nextToken(); - return Integer.parseInt(token); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Simple.java b/test/jdk/sun/util/calendar/zi/Simple.java deleted file mode 100644 index 0889155a99e..00000000000 --- a/test/jdk/sun/util/calendar/zi/Simple.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * Simple generates TimeZoneData, which had been used as internal - * data of TimeZone before J2SDK1.3. - * Since J2SDK1.4 doesn't need TimeZoneData, this class is for maintenance - * of old JDK release. - */ -class Simple extends BackEnd { - - /** - * Zone records which are applied for given year. - */ - private static Map lastZoneRecs = new HashMap<>(); - - /** - * Rule records which are applied for given year. - */ - private static Map> lastRules = new TreeMap<>(); - - /** - * zone IDs sorted by their GMT offsets. If zone's GMT - * offset will change in the future, its last known offset is - * used. - */ - private SortedMap> zonesByOffset = new TreeMap<>(); - - /** - * Sets last Rule records and Zone records for given timezone to - * each Map. - * - * @param tz Timezone object for each zone - * @return always 0 - */ - int processZoneinfo(Timezone tz) { - String zonename = tz.getName(); - - lastRules.put(zonename, tz.getLastRules()); - lastZoneRecs.put(zonename, tz.getLastZoneRec()); - - // Populate zonesByOffset. (Zones that will change their - // GMT offsets are also added to zonesByOffset here.) - int lastKnownOffset = tz.getRawOffset(); - Set set = zonesByOffset.get(lastKnownOffset); - if (set == null) { - set = new TreeSet<>(); - zonesByOffset.put(lastKnownOffset, set); - } - set.add(zonename); - - return 0; - } - - /** - * Generates TimeZoneData to output SimpleTimeZone data. - * @param map Mappings object which is generated by {@link Main#compile}. - * @return 0 if no error occurred, otherwise 1. - */ - int generateSrc(Mappings map) { - try { - File outD = new File(Main.getOutputDir()); - outD.mkdirs(); - - FileWriter fw = - new FileWriter(new File(outD, "TimeZoneData.java"), false); - BufferedWriter out = new BufferedWriter(fw); - - out.write("import java.util.SimpleTimeZone;\n\n"); - out.write(" static SimpleTimeZone zones[] = {\n"); - - Map a = map.getAliases(); - List roi = map.getRawOffsetsIndex(); - List> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (int offset : zonesByOffset.keySet()) { - int o = roi.get(index); - Set set = zonesByOffset.get(offset); - if (offset == o) { - // Merge aliases into zonesByOffset - set.addAll(roit.get(index)); - } - index++; - - for (String key : set) { - ZoneRec zrec; - String realname; - List stz; - if ((realname = a.get(key)) != null) { - // if this alias is not targeted, ignore it. - if (!Zone.isTargetZone(key)) { - continue; - } - stz = lastRules.get(realname); - zrec = lastZoneRecs.get(realname); - } else { - stz = lastRules.get(key); - zrec = lastZoneRecs.get(key); - } - - out.write("\t//--------------------------------------------------------------------\n"); - String s = Time.toFormedString(offset); - out.write("\tnew SimpleTimeZone(" + - Time.toFormedString(offset) + ", \"" + key + "\""); - if (realname != null) { - out.write(" /* " + realname + " */"); - } - - if (stz == null) { - out.write("),\n"); - } else { - RuleRec rr0 = stz.get(0); - RuleRec rr1 = stz.get(1); - - out.write(",\n\t " + Month.toString(rr0.getMonthNum()) + - ", " + rr0.getDay().getDayForSimpleTimeZone() + ", " + - rr0.getDay().getDayOfWeekForSimpleTimeZone() + ", " + - Time.toFormedString((int)rr0.getTime().getTime()) + ", " + - rr0.getTime().getTypeForSimpleTimeZone() + ",\n" + - - "\t " + Month.toString(rr1.getMonthNum()) + ", " + - rr1.getDay().getDayForSimpleTimeZone() + ", " + - rr1.getDay().getDayOfWeekForSimpleTimeZone() + ", " + - Time.toFormedString((int)rr1.getTime().getTime())+ ", " + - rr1.getTime().getTypeForSimpleTimeZone() + ",\n" + - - "\t " + Time.toFormedString(rr0.getSave()) + "),\n"); - - out.write("\t// " + rr0.getLine() + "\n"); - out.write("\t// " + rr1.getLine() + "\n"); - } - - String zline = zrec.getLine(); - if (zline.indexOf("Zone") == -1) { - zline = "Zone " + key + "\t" + zline.trim(); - } - out.write("\t// " + zline + "\n"); - } - } - out.write(" };\n"); - - out.close(); - fw.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } -} diff --git a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java deleted file mode 100644 index 0b6570b74dc..00000000000 --- a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8007572 8008161 8157792 8212970 8224560 8324065 - * @summary Test whether the TimeZone generated from JSR310 tzdb is the same - * as the one from the tz data from javazic - * @modules java.base/sun.util.calendar:+open - * @build BackEnd Checksum DayOfWeek Gen GenDoc Main Mappings Month - * Rule RuleDay RuleRec Simple TestZoneInfo310 Time Timezone - * TzIDOldMapping Zone ZoneInfoFile ZoneInfoOld ZoneRec Zoneinfo - * @run main TestZoneInfo310 - */ - -import java.io.File; -import java.lang.reflect.*; -import java.nio.file.*; -import java.util.*; -import java.util.regex.*; -import java.time.zone.*; -import java.time.ZoneId; - -public class TestZoneInfo310 { - - public static void main(String[] args) throws Throwable { - - String TESTDIR = System.getProperty("test.dir", "."); - Path tzdir = Paths.get(System.getProperty("test.root"), - "../../src/java.base/share/data/tzdata"); - String tzfiles = "africa antarctica asia australasia europe northamerica southamerica backward etcetera gmt"; - Path jdk_tzdir = Paths.get(System.getProperty("test.src"), "tzdata_jdk"); - String jdk_tzfiles = "jdk11_backward"; - String zidir = TESTDIR + File.separator + "zi"; - File fZidir = new File(zidir); - if (!fZidir.exists()) { - fZidir.mkdirs(); - } - Matcher m = Pattern.compile("tzdata(?[0-9]{4}[A-z])") - .matcher(new String(Files.readAllBytes(tzdir.resolve("VERSION")), "ascii")); - String ver = m.find() ? m.group("ver") : "NULL"; - - ArrayList alist = new ArrayList<>(); - alist.add("-V"); - alist.add(ver); - alist.add("-d"); - alist.add(zidir); - for (String f : tzfiles.split(" ")) { - alist.add(tzdir.resolve(f).toString()); - } - for (String f : jdk_tzfiles.split(" ")) { - alist.add(jdk_tzdir.resolve(f).toString()); - } - System.out.println("Compiling tz files!"); - Main.main(alist.toArray(new String[alist.size()])); - - ////////////////////////////////// - System.out.println("testing!"); - ZoneInfoFile.ziDir = zidir; - long t0, t1; - - t0 = System.nanoTime(); - ZoneInfoOld.getTimeZone("America/Los_Angeles"); - t1 = System.nanoTime(); - System.out.printf("OLD.getZoneInfoOld()[1]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - ZoneInfoOld.getTimeZone("America/New_York"); - t1 = System.nanoTime(); - System.out.printf("OLD.getZoneInfoOld()[2]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - ZoneInfoOld.getTimeZone("America/Denver"); - t1 = System.nanoTime(); - System.out.printf("OLD.getZoneInfoOld()[3]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - String[] zids_old = ZoneInfoOld.getAvailableIDs(); - t1 = System.nanoTime(); - System.out.printf("OLD.getAvailableIDs()=%d, total=%d%n", - (t1 - t0) / 1000, zids_old.length); - Arrays.sort(zids_old); - - t0 = System.nanoTime(); - String[] alias_old = ZoneInfoOld.getAliasTable() - .keySet().toArray(new String[0]); - t1 = System.nanoTime(); - System.out.printf("OLD.getAliasTable()=%d, total=%d%n", - (t1 - t0) / 1000, alias_old.length); - Arrays.sort(alias_old); - - t0 = System.currentTimeMillis(); - for (String zid : zids_old) { - ZoneInfoOld.getTimeZone(zid); - } - t1 = System.currentTimeMillis(); - System.out.printf("OLD.TotalTZ()=%d (ms)%n", t1 - t0); - -/* - t0 = System.nanoTime(); - ZoneId.of("America/Los_Angeles").getRules(); - t1 = System.nanoTime(); - System.out.printf("NEW.ZoneId.of()[1]=%d%n", (t1 - t0) / 1000); -*/ - t0 = System.nanoTime(); - TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); - t1 = System.nanoTime(); - System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - tz = TimeZone.getTimeZone("America/New_York"); - t1 = System.nanoTime(); - System.out.printf("NEW.getTimeZone()[2]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - tz = TimeZone.getTimeZone("America/Denver"); - t1 = System.nanoTime(); - System.out.printf("NEW.getTimeZone()[3]=%d%n", (t1 - t0) / 1000); - - t0 = System.nanoTime(); - String[] zids_new = TimeZone.getAvailableIDs(); - t1 = System.nanoTime(); - System.out.printf("NEW.getAvailableIDs()=%d, total=%d%n", - (t1 - t0) / 1000, zids_new.length); - Arrays.sort(zids_new); - - t0 = System.nanoTime(); - String[] alias_new = sun.util.calendar.ZoneInfo.getAliasTable() - .keySet().toArray(new String[0]); - t1 = System.nanoTime(); - System.out.printf("NEW.getAliasTable()=%d, total=%d%n", - (t1 - t0) / 1000, alias_new.length); - Arrays.sort(alias_new); - - t0 = System.currentTimeMillis(); - for (String zid : zids_new) { - TimeZone.getTimeZone(zid); - } - t1 = System.currentTimeMillis(); - System.out.printf("NEW.TotalTZ()=%d (ms)%n", t1 - t0); - - if (!Arrays.equals(zids_old, zids_new)) { - throw new RuntimeException(" FAILED: availableIds don't match"); - } - - if (!Arrays.equals(alias_old, alias_new)) { - throw new RuntimeException(" FAILED: aliases don't match"); - } - - for (String zid : zids_new) { - ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid)); - ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid); - /* - * Ignoring the failing TimeZones which have negative DST - * save time in IANA tzdata, as javazic/ZoneInfoOld cannot - * handle the negative DST. - * - * These are the zones/rules that employ negative DST in vanguard - * format (as of 2019a), Palestine added in 2022d: - * - * - Rule "Eire" - * - Rule "Morocco" - * - Rule "Namibia" - * - Rule "Palestine" - * - Zone "Europe/Prague" - */ - if (zid.equals("Africa/Casablanca") || // uses "Morocco" rule - zid.equals("Africa/El_Aaiun") || // uses "Morocco" rule - zid.equals("Africa/Windhoek") || // uses "Namibia" rule - zid.equals("Eire") || - zid.equals("Europe/Bratislava") || // link to "Europe/Prague" - zid.equals("Europe/Dublin") || // uses "Eire" rule - zid.equals("Europe/Prague") || - zid.equals("Asia/Gaza") || // uses "Palestine" rule - zid.equals("Asia/Hebron")) { // uses "Palestine" rule - continue; - } - if (! zi.equalsTo(ziOLD)) { - System.out.println(zi.diffsTo(ziOLD)); - throw new RuntimeException(" FAILED: " + zid); - } - } - delete(fZidir); - - // test tzdb version - if (!ver.equals(sun.util.calendar.ZoneInfoFile.getVersion())) { - System.out.printf(" FAILED: ver=%s, expected=%s%n", - sun.util.calendar.ZoneInfoFile.getVersion(), ver); - throw new RuntimeException("Version test failed"); - } - - // test getAvailableIDs(raw); - zids_new = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); - Arrays.sort(zids_new); - zids_old = ZoneInfoOld.getAvailableIDs(-8 * 60 * 60 * 1000); - Arrays.sort(zids_old); - if (!Arrays.equals(zids_new, zids_old)) { - System.out.println("------------------------"); - System.out.println("NEW.getAvailableIDs(-8:00)"); - for (String zid : zids_new) { - System.out.println(zid); - } - System.out.println("------------------------"); - System.out.println("OLD.getAvailableIDs(-8:00)"); - for (String zid : zids_old) { - System.out.println(zid); - } - throw new RuntimeException(" FAILED: availableIds(offset) don't match"); - } - } - - private static void delete(File f) { - if (f.isDirectory()) { - for (File f0 : f.listFiles()) { - delete(f0); - } - } - f.delete(); - } - - // to access sun.util.calendar.ZoneInfo's private fields - static Class ziClz; - static Field rawOffset; - static Field checksum; - static Field dstSavings; - static Field transitions; - static Field offsets; - static Field simpleTimeZoneParams; - static Field willGMTOffsetChange; - static { - try { - ziClz = Class.forName("sun.util.calendar.ZoneInfo"); - rawOffset = ziClz.getDeclaredField("rawOffset"); - checksum = ziClz.getDeclaredField("checksum"); - dstSavings = ziClz.getDeclaredField("dstSavings"); - transitions = ziClz.getDeclaredField("transitions"); - offsets = ziClz.getDeclaredField("offsets"); - simpleTimeZoneParams = ziClz.getDeclaredField("simpleTimeZoneParams"); - willGMTOffsetChange = ziClz.getDeclaredField("willGMTOffsetChange"); - rawOffset.setAccessible(true); - checksum.setAccessible(true); - dstSavings.setAccessible(true); - transitions.setAccessible(true); - offsets.setAccessible(true); - simpleTimeZoneParams.setAccessible(true); - willGMTOffsetChange.setAccessible(true); - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - private static ZoneInfoOld toZoneInfoOld(TimeZone tz) throws Exception { - return new ZoneInfoOld(tz.getID(), - rawOffset.getInt(tz), - dstSavings.getInt(tz), - checksum.getInt(tz), - (long[])transitions.get(tz), - (int[])offsets.get(tz), - (int[])simpleTimeZoneParams.get(tz), - willGMTOffsetChange.getBoolean(tz)); - } - -} diff --git a/test/jdk/sun/util/calendar/zi/Time.java b/test/jdk/sun/util/calendar/zi/Time.java deleted file mode 100644 index 66379d29d28..00000000000 --- a/test/jdk/sun/util/calendar/zi/Time.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.Locale; -import sun.util.calendar.CalendarDate; -import sun.util.calendar.CalendarSystem; -import sun.util.calendar.Gregorian; - -/** - * Time class represents the "AT" field and other time related information. - * - * @since 1.4 - */ -class Time { - - static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); - - // type is wall clock time - private static final int WALL = 1; - - // type is standard time - private static final int STD = 2; - - // type is UTC - private static final int UTC = 3; - - // type of representing time - private int type; - - /** - * Time from the EPOCH in milliseconds - */ - private long time; - - /** - * Current time in milliseconds - */ - private static final long currentTime = System.currentTimeMillis(); - - Time() { - time = 0L; - } - - Time(long time) { - this.time = time; - } - - void setType(int type) { - this.type = type; - } - - long getTime() { - return time; - } - - int getType() { - return type; - } - - static long getCurrentTime() { - return currentTime; - } - - /** - * @return true if the time is represented in wall-clock time. - */ - boolean isWall() { - return type == WALL; - } - - /** - * @return true if the time is represented in standard time. - */ - boolean isSTD() { - return type == STD; - } - - /** - * @return true if the time is represented in UTC time. - */ - boolean isUTC() { - return type == UTC; - } - - /** - * Converts the type to a string that represents the type in the - * SimpleTimeZone time mode. (e.g., "SimpleTimeZone.WALL_TIME"). - * @return the converted string or null if the type is undefined. - */ - String getTypeForSimpleTimeZone() { - String stz = "SimpleTimeZone."; - if (isWall()) { - return stz+"WALL_TIME"; - } - else if (isSTD()) { - return stz+"STANDARD_TIME"; - } - else if (isUTC()) { - return stz+"UTC_TIME"; - } - else { - return null; - } - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param save the amount of daylight time in milliseconds - * @param gmtOffset the GMT offset in milliseconds - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, int save, - int gmtOffset, Time time) { - long t = time.getTime(); - - if (time.isSTD()) - t = time.getTime() + save; - else if (time.isUTC()) - t = time.getTime() + save + gmtOffset; - - return getLocalTime(year, month, day, t); - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day value - * @param time the time of the day in milliseconds - * @return local time - */ - static long getLocalTime(int year, Month month, int day, long time) { - CalendarDate date = gcal.newCalendarDate(null); - date.setDate(year, month.value(), day); - long millis = gcal.getTime(date); - return millis + time; - } - - /** - * Equivalent to getLocalTime(year, month, day, (long)time). - * @param year the year value - * @param month the Month value - * @param day the day value - * @param time the time of the day in milliseconds - * @return local time - */ - static long getLocalTime(int year, Month month, int day, int time) { - return getLocalTime(year, month, day, (long)time); - } - - /** - * Equivalent to {@link #getLocalTime(int, Month, RuleDay, int) - * getLocalTime(year, month, day, (int) time)}. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, long time) { - return getLocalTime(year, month, day, (int) time); - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, int time) { - CalendarDate cdate = gcal.newCalendarDate(null); - int monthValue = month.value(); - - if (day.isLast()) { // e.g., "lastSun" - cdate.setDate(year, monthValue, 1); - cdate.setDayOfMonth(gcal.getMonthLength(cdate)); - cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); - } else if (day.isLater()) { // e.g., "Sun>=1" - cdate.setDate(year, monthValue, day.getDay()); - cdate = gcal.getNthDayOfWeek(1, day.getDayOfWeekNum(), cdate); - } else if (day.isExact()) { - cdate.setDate(year, monthValue, day.getDay()); - } else if (day.isEarlier()) { // e.g., "Sun<=15" - cdate.setDate(year, monthValue, day.getDay()); - cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); - } else { - Main.panic("invalid day type: " + day); - } - return gcal.getTime(cdate) + time; - } - - /** - * Parses the given "AT" field and constructs a Time object. - * @param the "AT" field string - * @return the Time object - */ - static Time parse(String time) { - int sign; - int index = 0; - Time tm; - - if (time.charAt(0) == '-') { - sign = -1; - index++; - } else { - sign = 1; - } - int val = 0; - int num = 0; - int countDelim = 0; - while (index < time.length()) { - char c = time.charAt(index++); - if (c == ':') { - val = val * 60 + num; - countDelim++; - num = 0; - continue; - } - int d = Character.digit(c, 10); - if (d == -1) { - --index; - break; - } - num = num * 10 + d; - } - val = val * 60 + num; - // convert val to second - for (; countDelim < 2; countDelim++) { - val *= 60; - } - tm = new Time((long)val * 1000 * sign); - if (index < time.length()) { - char c = time.charAt(index++); - if (c == 's') { - tm.setType(Time.STD); - } else if (c == 'u' || c == 'g' || c == 'z') { - tm.setType(Time.UTC); - } else if (c == 'w') { - tm.setType(Time.WALL); - } else { - Main.panic("unknown time mode: "+c); - } - } else { - tm.setType(Time.WALL); - } - return tm; - } - - /** - * Converts the given milliseconds string to a "[+-]hh:mm" string. - * @param ms the milliseconds string - */ - static String toGMTFormat(String ms) { - long sec = Long.parseLong(ms) / 1000; - char sign; - if (sec < 0) { - sign = '-'; - sec = -sec; - } else { - sign = '+'; - } - return String.format((Locale)null, "%c%02d:%02d", - sign, sec/3600, (sec%3600)/60); - } - - /** - * Converts the given millisecond value to a string for a - * SimpleTimeZone parameter. - * @param ms the millisecond value - * @return the string in a human readable form - */ - static String toFormedString(int ms) { - StringBuilder s = new StringBuilder(); - boolean minus = false; - - if (ms < 0) { - s.append("-"); - minus = true; - ms = -ms; - } else if (ms == 0) { - return "0"; - } - - int hour = ms / (60 * 60 * 1000); - ms %= (60 * 60 * 1000); - int minute = ms / (60 * 1000); - - if (hour != 0) { - if (minus && minute != 0) { - s.append("("); - } - s.append(Integer.toString(hour) + "*ONE_HOUR"); - } - - if (minute != 0) { - if (hour != 0) { - s.append("+"); - } - s.append(Integer.toString(minute) + "*ONE_MINUTE"); - if (minus && hour != 0) { - s.append(")"); - } - } - - return s.toString(); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Timezone.java b/test/jdk/sun/util/calendar/zi/Timezone.java deleted file mode 100644 index d4890e8f58b..00000000000 --- a/test/jdk/sun/util/calendar/zi/Timezone.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.ArrayList; -import java.util.List; - -/** - * Timezone represents all information of a single point of time to - * generate its time zone database. - * - * @since 1.4 - */ -class Timezone { - /** - * zone name of this time zone - */ - private String name; - - /** - * transition time values in UTC (millisecond) - */ - private List transitions; - - /** - * All offset values in millisecond - * @see sun.util.calendar.ZoneInfo - */ - private List offsets; - - /** - * Indices of GMT offset values (both raw and raw+saving) - * at transitions - */ - private List gmtOffsets; - - /** - * Indices of regular or "direct" saving time values - * at transitions - */ - private List dstOffsets; - - /** - * Zone records of this time zone - */ - private List usedZoneRecs; - - /** - * Rule records referred to by this time zone - */ - private List usedRuleRecs; - - /** - * Type of DST rules in this time zone - */ - private int dstType; - static final int UNDEF_DST = 0; // DST type not set yet - static final int NO_DST = 1; // never observed DST - static final int LAST_DST = 2; // last rule ends in DST (all year round DST-only) - static final int X_DST = 3; // used to observe DST - static final int DST = 4; // observing DST regularly - - /** - * Raw GMT offset of this time zone in the last rule - */ - private int rawOffset; - - /** - * The CRC32 value of the transitions data - */ - private int crc32; - - /** - * The last ZoneRec - */ - private ZoneRec lastZoneRec; - - /** - * The last DST rules. lastRules[0] is the DST start - * rule. lastRules[1] is the DST end rules. - */ - private List lastRules; - - /** - * The amount of DST saving value (millisecond) in the last DST - * rule. - */ - private int lastSaving; - - /** - * true if the raw offset will change in the future time. - */ - private boolean willRawOffsetChange = false; - - - /** - * Constracts a Timezone object with the given zone name. - * @param name the zone name - */ - Timezone(String name) { - this.name = name; - } - - /** - * @return the number of transitions - */ - int getNTransitions() { - if (transitions == null) { - return 0; - } - return transitions.size(); - } - - /** - * @return the zone name - */ - String getName() { - return name; - } - - /** - * Returns the list of all rule records that have been referred to - * by this time zone. - * @return the rule records list - */ - List getRules() { - return usedRuleRecs; - } - - /** - * Returns the list of all zone records that have been referred to - * by this time zone. - * @return the zone records list - */ - List getZones() { - return usedZoneRecs; - } - - /** - * @return the transition table (list) - */ - List getTransitions() { - return transitions; - } - - /** - * @return the offsets list - */ - List getOffsets() { - return offsets; - } - - /** - * @return the DST saving offsets list - */ - List getDstOffsets() { - return dstOffsets; - } - - /** - * @return the GMT offsets list - */ - List getGmtOffsets() { - return gmtOffsets; - } - - /** - * @return the checksum (crc32) value of the trasition table - */ - int getCRC32() { - return crc32; - } - - /** - * @return true if the GMT offset of this time zone would change - * after the time zone database has been generated, false, otherwise. - */ - boolean willGMTOffsetChange() { - return willRawOffsetChange; - } - - /** - * @return the last known GMT offset value in milliseconds - */ - int getRawOffset() { - return rawOffset; - } - - /** - * Sets time zone's GMT offset to offset. - * @param offset the GMT offset value in milliseconds - */ - void setRawOffset(int offset) { - rawOffset = offset; - } - - /** - * Sets time zone's GMT offset value to offset. If - * startTime is future time, then the {@link - * #willRawOffsetChange} value is set to true. - * @param offset the GMT offset value in milliseconds - * @param startTime the UTC time at which the GMT offset is in effective - */ - void setRawOffset(int offset, long startTime) { - // if this rawOffset is for the future time, let the run-time - // look for the current GMT offset. - if (startTime > Time.getCurrentTime()) { - willRawOffsetChange = true; - } - setRawOffset(offset); - } - - /** - * Adds the specified transition information to the end of the transition table. - * @param time the UTC time at which this transition happens - * @param offset the total amount of the offset from GMT in milliseconds - * @param dstOffset the amount of time in milliseconds saved at this transition - */ - void addTransition(long time, int offset, int dstOffset) { - if (transitions == null) { - transitions = new ArrayList(); - offsets = new ArrayList(); - dstOffsets = new ArrayList(); - } - transitions.add(time); - offsets.add(offset); - dstOffsets.add(dstOffset); - } - - /** - * Sets the type of historical daylight saving time - * observation. For example, China used to observed daylight - * saving time, but it no longer does. Then, X_DST is set to the - * China time zone. - * @param type the type of daylight saving time - */ - void setDSTType(int type) { - dstType = type; - } - - /** - * @return the type of historical daylight saving time - * observation. - */ - int getDSTType() { - return dstType; - } - - /** - * Adds the specified zone record to the zone records list. - * @param rec the zone record - */ - void addUsedRec(ZoneRec rec) { - if (usedZoneRecs == null) { - usedZoneRecs = new ArrayList(); - } - usedZoneRecs.add(rec); - } - - /** - * Adds the specified rule record to the rule records list. - * @param rec the rule record - */ - void addUsedRec(RuleRec rec) { - if (usedRuleRecs == null) { - usedRuleRecs = new ArrayList(); - } - // if the last used rec is the same as the given rec, avoid - // putting the same rule. - int n = usedRuleRecs.size(); - for (int i = 0; i < n; i++) { - if (usedRuleRecs.get(i).equals(rec)) { - return; - } - } - usedRuleRecs.add(rec); - } - - /** - * Sets the last zone record for this time zone. - * @param the last zone record - */ - void setLastZoneRec(ZoneRec zrec) { - lastZoneRec = zrec; - } - - /** - * @return the last zone record for this time zone. - */ - ZoneRec getLastZoneRec() { - return lastZoneRec; - } - - /** - * Sets the last rule records for this time zone. Those are used - * for generating SimpleTimeZone parameters. - * @param rules the last rule records - */ - void setLastRules(List rules) { - int n = rules.size(); - if (n > 0) { - lastRules = rules; - RuleRec rec = rules.get(0); - int offset = rec.getSave(); - if (offset > 0) { - setLastDSTSaving(offset); - } else { - System.err.println("\t No DST starting rule in the last rules."); - } - } - } - - /** - * @return the last rule records for this time zone. - */ - List getLastRules() { - return lastRules; - } - - /** - * Sets the last daylight saving amount. - * @param the daylight saving amount - */ - void setLastDSTSaving(int offset) { - lastSaving = offset; - } - - /** - * @return the last daylight saving amount. - */ - int getLastDSTSaving() { - return lastSaving; - } - - /** - * Calculates the CRC32 value from the transition table and sets - * the value to crc32. - */ - void checksum() { - if (transitions == null) { - crc32 = 0; - return; - } - Checksum sum = new Checksum(); - for (int i = 0; i < transitions.size(); i++) { - int offset = offsets.get(i); - // adjust back to make the transition in local time - sum.update(transitions.get(i) + offset); - sum.update(offset); - sum.update(dstOffsets.get(i)); - } - crc32 = (int)sum.getValue(); - } - - /** - * Removes unnecessary transitions for Java time zone support. - */ - void optimize() { - // if there is only one offset, delete all transitions. This - // could happen if only time zone abbreviations changed. - if (gmtOffsets.size() == 1) { - transitions = null; - usedRuleRecs = null; - setDSTType(NO_DST); - return; - } - for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one - if (transitions.get(i) == transitions.get(i+1)) { - transitions.remove(i); - offsets.remove(i); - dstOffsets.remove(i); - i--; - } - } - - for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one - if (offsets.get(i) == offsets.get(i+1) - && dstOffsets.get(i) == dstOffsets.get(i+1)) { - transitions.remove(i+1); - offsets.remove(i+1); - dstOffsets.remove(i+1); - i--; - } - } - } - - /** - * Stores the specified offset value from GMT in the GMT offsets - * table and returns its index. The offset value includes the base - * GMT offset and any additional daylight saving if applicable. If - * the same value as the specified offset is already in the table, - * its index is returned. - * @param offset the offset value in milliseconds - * @return the index to the offset value in the GMT offsets table. - */ - int getOffsetIndex(int offset) { - return getOffsetIndex(offset, 0); - } - - /** - * Stores the specified daylight saving value in the GMT offsets - * table and returns its index. If the same value as the specified - * offset is already in the table, its index is returned. If 0 is - * specified, it's not stored in the table and -1 is returned. - * @param offset the offset value in milliseconds - * @return the index to the specified offset value in the GMT - * offsets table, or -1 if 0 is specified. - */ - int getDstOffsetIndex(int offset) { - if (offset == 0) { - return -1; - } - return getOffsetIndex(offset, 1); - } - - private int getOffsetIndex(int offset, int index) { - if (gmtOffsets == null) { - gmtOffsets = new ArrayList(); - } - for (int i = index; i < gmtOffsets.size(); i++) { - if (offset == gmtOffsets.get(i)) { - return i; - } - } - if (gmtOffsets.size() < index) { - gmtOffsets.add(0); - } - gmtOffsets.add(offset); - return gmtOffsets.size() - 1; - } -} diff --git a/test/jdk/sun/util/calendar/zi/TzIDOldMapping.java b/test/jdk/sun/util/calendar/zi/TzIDOldMapping.java deleted file mode 100644 index 7e8ce636449..00000000000 --- a/test/jdk/sun/util/calendar/zi/TzIDOldMapping.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.Map; -import java.util.HashMap; - -class TzIDOldMapping { - static final Map MAP = new HashMap(); - static { - String[][] oldmap = { - { "ACT", "Australia/Darwin" }, - { "AET", "Australia/Sydney" }, - { "AGT", "America/Argentina/Buenos_Aires" }, - { "ART", "Africa/Cairo" }, - { "AST", "America/Anchorage" }, - { "BET", "America/Sao_Paulo" }, - { "BST", "Asia/Dhaka" }, - { "CAT", "Africa/Harare" }, - { "CNT", "America/St_Johns" }, - { "CST", "America/Chicago" }, - { "CTT", "Asia/Shanghai" }, - { "EAT", "Africa/Addis_Ababa" }, - { "ECT", "Europe/Paris" }, - { "EST", "America/New_York" }, - { "HST", "Pacific/Honolulu" }, - { "IET", "America/Indianapolis" }, - { "IST", "Asia/Calcutta" }, - { "JST", "Asia/Tokyo" }, - { "MIT", "Pacific/Apia" }, - { "MST", "America/Denver" }, - { "NET", "Asia/Yerevan" }, - { "NST", "Pacific/Auckland" }, - { "PLT", "Asia/Karachi" }, - { "PNT", "America/Phoenix" }, - { "PRT", "America/Puerto_Rico" }, - { "PST", "America/Los_Angeles" }, - { "SST", "Pacific/Guadalcanal" }, - { "VST", "Asia/Saigon" }, - }; - for (String[] pair : oldmap) { - MAP.put(pair[0], pair[1]); - } - } -} diff --git a/test/jdk/sun/util/calendar/zi/Zone.java b/test/jdk/sun/util/calendar/zi/Zone.java deleted file mode 100644 index f1adbf6f938..00000000000 --- a/test/jdk/sun/util/calendar/zi/Zone.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; - -/** - * Zone holds information corresponding to a "Zone" part of a time - * zone definition file. - * - * @since 1.4 - */ -class Zone { - // zone name (e.g., "America/Los_Angeles") - private String name; - - // zone records - private List list; - - // target zone names for this compilation - private static Set targetZones; - - /** - * Constructs a Zone with the specified zone name. - * @param name the zone name - */ - Zone(String name) { - this.name = name; - list = new ArrayList(); - } - - /** - * Reads time zone names to be generated, called "target zone - * name", from the specified text file and creats an internal hash - * table to keep those names. It's assumed that one text line - * contains a zone name or comments if it starts with - * '#'. Comments can't follow a zone name in a single line. - * @param fileName the text file name - */ - static void readZoneNames(String fileName) { - if (fileName == null) { - return; - } - BufferedReader in = null; - try { - FileReader fr = new FileReader(fileName); - in = new BufferedReader(fr); - } catch (FileNotFoundException e) { - Main.panic("can't open file: " + fileName); - } - targetZones = new HashSet(); - String line; - - try { - while ((line = in.readLine()) != null) { - line = line.trim(); - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - if (!targetZones.add(line)) { - Main.warning("duplicated target zone name: " + line); - } - } - in.close(); - } catch (IOException e) { - Main.panic("IO error: "+e.getMessage()); - } - } - - /** - * Determines whether the specified zone is one of the target zones. - * If no target zones are specified, this method always returns - * true for any zone name. - * @param zoneName the zone name - * @return true if the specified name is a target zone. - */ - static boolean isTargetZone(String zoneName) { - if (targetZones == null) { - return true; - } - return targetZones.contains(zoneName); - } - - /** - * Forces to add "MET" to the target zone table. This is because - * there is a conflict between Java zone name "WET" and Olson zone - * name. - */ - static void addMET() { - if (targetZones != null) { - targetZones.add("MET"); - } - } - - /** - * @return the zone name - */ - String getName() { - return name; - } - - /** - * Adds the specified zone record to the zone record list. - */ - void add(ZoneRec rec) { - list.add(rec); - } - - /** - * @param index the index at which the zone record in the list is returned. - * @return the zone record specified by the index. - */ - ZoneRec get(int index) { - return list.get(index); - } - - /** - * @return the size of the zone record list - */ - int size() { - return list.size(); - } - - /** - * Resolves the reference to a rule in each zone record. - * @param zi the Zoneinfo object with which the rule reference is - * resolved. - */ - void resolve(Zoneinfo zi) { - for (int i = 0; i < list.size(); i++) { - ZoneRec rec = list.get(i); - rec.resolve(zi); - } - } -} diff --git a/test/jdk/sun/util/calendar/zi/ZoneInfoFile.java b/test/jdk/sun/util/calendar/zi/ZoneInfoFile.java deleted file mode 100644 index 3134a517979..00000000000 --- a/test/jdk/sun/util/calendar/zi/ZoneInfoFile.java +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.lang.ref.SoftReference; -import java.nio.file.FileSystems; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import sun.util.calendar.*; - -/** - * ZoneInfoFile reads Zone information files in the - * <java.home>/lib/zi directory and provides time zone - * information in the form of a {@link ZoneInfo} object. Also, it - * reads the ZoneInfoMappings file to obtain time zone IDs information - * that is used by the {@link ZoneInfo} class. The directory layout - * and data file formats are as follows. - * - *

    Directory layout

    - * - * All zone data files and ZoneInfoMappings are put under the - * <java.home>/lib/zi directory. A path name for a given time - * zone ID is a concatenation of <java.home>/lib/zi/ and the - * time zone ID. (The file separator is replaced with the platform - * dependent value. e.g., '\' for Win32.) An example layout will look - * like as follows. - *

    - *
    - * <java.home>/lib/zi/Africa/Addis_Ababa
    - *                   /Africa/Dakar
    - *                   /America/Los_Angeles
    - *                   /Asia/Singapore
    - *                   /EET
    - *                   /Europe/Oslo
    - *                   /GMT
    - *                   /Pacific/Galapagos
    - *                       ...
    - *                   /ZoneInfoMappings
    - * 
    - *
    - * - * A zone data file has specific information of each zone. - * ZoneInfoMappings has global information of zone IDs so - * that the information can be obtained without instantiating all time - * zones. - * - *

    File format

    - * - * Two binary-file formats based on a simple Tag-Length-Value format are used - * to describe TimeZone information. The generic format of a data file is: - *

    - *
    - *    DataFile {
    - *      u1              magic[7];
    - *      u1              version;
    - *      data_item       data[];
    - *    }
    - * 
    - *
    - * where magic is a magic number identifying a file - * format, version is the format version number, and - * data is one or more data_items. The - * data_item structure is: - *
    - *
    - *    data_item {
    - *      u1              tag;
    - *      u2              length;
    - *      u1              value[length];
    - *    }
    - * 
    - *
    - * where tag indicates the data type of the item, - * length is a byte count of the following - * value that is the content of item data. - *

    - * All data is stored in the big-endian order. There is no boundary - * alignment between date items. - * - *

    1. ZoneInfo data file

    - * - * Each ZoneInfo data file consists of the following members. - *
    - *

    - *
    - *    ZoneInfoDataFile {
    - *      u1              magic[7];
    - *      u1              version;
    - *      SET OF1 {
    - *        transition            transitions2;
    - *        offset_table          offsets2;
    - *        simpletimezone        stzparams2;
    - *        raw_offset            rawoffset;
    - *        dstsaving             dst;
    - *        checksum              crc32;
    - *        gmtoffsetwillchange   gmtflag2;
    - *      }
    - *   }
    - *   1: an unordered collection of zero or one occurrences of each item
    - *   2: optional item
    - * 
    - *
    - * magic is a byte-string constant identifying the - * ZoneInfo data file. This field must be "javazi\0" - * defined as {@link #JAVAZI_LABEL}. - *

    - * version is the version number of the file format. This - * will be used for compatibility check. This field must be - * 0x01 in this version. - *

    - * transition, offset_table and - * simpletimezone have information of time transition - * from the past to the future. Therefore, these structures don't - * exist if the zone didn't change zone names and haven't applied DST in - * the past, and haven't planned to apply it. (e.g. Asia/Tokyo zone) - *

    - * raw_offset, dstsaving and checksum - * exist in every zoneinfo file. They are used by TimeZone.class indirectly. - * - *

    1.1 transition structure

    - *

    - *
    - *    transition {
    - *      u1      tag;              // 0x04 : constant
    - *      u2      length;           // byte length of whole values
    - *      s8      value[length/8];  // transitions in `long'
    - *    }
    - * 
    - *
    - * See {@link ZoneInfo#transitions ZoneInfo.transitions} about the value. - * - *

    1.2 offset_table structure

    - *

    - *
    - *    offset_table {
    - *      u1      tag;              // 0x05 : constant
    - *      u2      length;           // byte length of whole values
    - *      s4      value[length/4];  // offset values in `int'
    - *    }
    - * 
    - *
    - * - *

    1.3 simpletimezone structure

    - * See {@link ZoneInfo#simpleTimeZoneParams ZoneInfo.simpleTimeZoneParams} - * about the value. - *

    - *
    - *    simpletimezone {
    - *      u1      tag;              // 0x06 : constant
    - *      u2      length;           // byte length of whole values
    - *      s4      value[length/4];  // SimpleTimeZone parameters
    - *    }
    - * 
    - *
    - * See {@link ZoneInfo#offsets ZoneInfo.offsets} about the value. - * - *

    1.4 raw_offset structure

    - *

    - *
    - *    raw_offset {
    - *      u1      tag;              // 0x01 : constant
    - *      u2      length;           // must be 4.
    - *      s4      value;            // raw GMT offset [millisecond]
    - *    }
    - * 
    - *
    - * See {@link ZoneInfo#rawOffset ZoneInfo.rawOffset} about the value. - * - *

    1.5 dstsaving structure

    - * Value has dstSaving in seconds. - *

    - *
    - *    dstsaving {
    - *      u1      tag;              // 0x02 : constant
    - *      u2      length;           // must be 2.
    - *      s2      value;            // DST save value [second]
    - *    }
    - * 
    - *
    - * See {@link ZoneInfo#dstSavings ZoneInfo.dstSavings} about value. - * - *

    1.6 checksum structure

    - *

    - *
    - *    checksum {
    - *      u1      tag;              // 0x03 : constant
    - *      u2      length;           // must be 4.
    - *      s4      value;            // CRC32 value of transitions
    - *    }
    - * 
    - *
    - * See {@link ZoneInfo#checksum ZoneInfo.checksum}. - * - *

    1.7 gmtoffsetwillchange structure

    - * This record has a flag value for {@link ZoneInfo#rawOffsetWillChange}. - * If this record is not present in a zoneinfo file, 0 is assumed for - * the value. - *

    - *
    - *    gmtoffsetwillchange {
    - *      u1      tag;             // 0x07 : constant
    - *      u2      length;          // must be 1.
    - *      u1      value;           // 1: if the GMT raw offset will change
    - *                               // in the future, 0, otherwise.
    - *     }
    - * 
    - *
    - * - * - *

    2. ZoneInfoMappings file

    - * - * The ZoneInfoMappings file consists of the following members. - *
    - *

    - *
    - *    ZoneInfoMappings {
    - *      u1      magic[7];
    - *      u1      version;
    - *      SET OF {
    - *        versionName                   version;
    - *        zone_id_table                 zoneIDs;
    - *        raw_offset_table              rawoffsets;
    - *        raw_offset_index_table        rawoffsetindices;
    - *        alias_table                   aliases;
    - *        excluded_list                 excludedList;
    - *      }
    - *   }
    - * 
    - *
    - * - * magic is a byte-string constant which has the file type. - * This field must be "javazm\0" defined as {@link #JAVAZM_LABEL}. - *

    - * version is the version number of this file - * format. This will be used for compatibility check. This field must - * be 0x01 in this version. - *

    - * versionName shows which version of Olson's data has been used - * to generate this ZoneInfoMappings. (e.g. tzdata2000g)
    - * This field is for trouble-shooting and isn't usually used in runtime. - *

    - * zone_id_table, raw_offset_index_table and - * alias_table are general information of supported - * zones. - * - *

    2.1 zone_id_table structure

    - * The list of zone IDs included in the zi database. The list does - * not include zone IDs, if any, listed in excludedList. - *
    - *

    - *
    - *    zone_id_table {
    - *      u1      tag;              // 0x40 : constant
    - *      u2      length;           // byte length of whole values
    - *      u2      zone_id_count;
    - *      zone_id value[zone_id_count];
    - *    }
    - *
    - *    zone_id {
    - *      u1      byte_length;      // byte length of id
    - *      u1      id[byte_length];  // zone name string
    - *    }
    - * 
    - *
    - * - *

    2.2 raw_offset_table structure

    - *
    - *

    - *
    - *    raw_offset_table {
    - *      u1      tag;              // 0x41 : constant
    - *      u2      length;           // byte length of whole values
    - *      s4      value[length/4];  // raw GMT offset in milliseconds
    - *   }
    - * 
    - *
    - * - *

    2.3 raw_offset_index_table structure

    - *
    - *

    - *
    - *    raw_offset_index_table {
    - *      u1      tag;              // 0x42 : constant
    - *      u2      length;           // byte length of whole values
    - *      u1      value[length];
    - *    }
    - * 
    - *
    - * - *

    2.4 alias_table structure

    - *
    - *

    - *
    - *   alias_table {
    - *      u1      tag;              // 0x43 : constant
    - *      u2      length;           // byte length of whole values
    - *      u2      nentries;         // number of id-pairs
    - *      id_pair value[nentries];
    - *   }
    - *
    - *   id_pair {
    - *      zone_id aliasname;
    - *      zone_id ID;
    - *   }
    - * 
    - *
    - * - *

    2.5 versionName structure

    - *
    - *

    - *
    - *   versionName {
    - *      u1      tag;              // 0x44 : constant
    - *      u2      length;           // byte length of whole values
    - *      u1      value[length];
    - *   }
    - * 
    - *
    - * - *

    2.6 excludeList structure

    - * The list of zone IDs whose zones will change their GMT offsets - * (a.k.a. raw offsets) some time in the future. Those IDs must be - * added to the list of zone IDs for getAvailableIDs(). Also they must - * be examined for getAvailableIDs(int) to determine the - * current GMT offsets. - *
    - *

    - *
    - *   excluded_list {
    - *      u1      tag;              // 0x45 : constant
    - *      u2      length;           // byte length of whole values
    - *      u2      nentries;         // number of zone_ids
    - *      zone_id value[nentries];  // excluded zone IDs
    - *   }
    - * 
    - *
    - * - * @since 1.4 - */ - -public class ZoneInfoFile { - - /** - * The magic number for the ZoneInfo data file format. - */ - public static final byte[] JAVAZI_LABEL = { - (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'i', (byte)'\0' - }; - private static final int JAVAZI_LABEL_LENGTH = JAVAZI_LABEL.length; - - /** - * The ZoneInfo data file format version number. Must increase - * one when any incompatible change has been made. - */ - public static final byte JAVAZI_VERSION = 0x01; - - /** - * Raw offset data item tag. - */ - public static final byte TAG_RawOffset = 1; - - /** - * Known last Daylight Saving Time save value data item tag. - */ - public static final byte TAG_LastDSTSaving = 2; - - /** - * Checksum data item tag. - */ - public static final byte TAG_CRC32 = 3; - - /** - * Transition data item tag. - */ - public static final byte TAG_Transition = 4; - - /** - * Offset table data item tag. - */ - public static final byte TAG_Offset = 5; - - /** - * SimpleTimeZone parameters data item tag. - */ - public static final byte TAG_SimpleTimeZone = 6; - - /** - * Raw GMT offset will change in the future. - */ - public static final byte TAG_GMTOffsetWillChange = 7; - - - /** - * The ZoneInfoMappings file name. - */ - public static final String JAVAZM_FILE_NAME = "ZoneInfoMappings"; - - /** - * The magic number for the ZoneInfoMappings file format. - */ - public static final byte[] JAVAZM_LABEL = { - (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'m', (byte)'\0' - }; - private static final int JAVAZM_LABEL_LENGTH = JAVAZM_LABEL.length; - - /** - * The ZoneInfoMappings file format version number. Must increase - * one when any incompatible change has been made. - */ - public static final byte JAVAZM_VERSION = 0x01; - - /** - * Time zone IDs data item tag. - */ - public static final byte TAG_ZoneIDs = 64; - - /** - * Raw GMT offsets table data item tag. - */ - public static final byte TAG_RawOffsets = 65; - - /** - * Indices to the raw GMT offset table data item tag. - */ - public static final byte TAG_RawOffsetIndices = 66; - - /** - * Time zone aliases table data item tag. - */ - public static final byte TAG_ZoneAliases = 67; - - /** - * Olson's public zone information version tag. - */ - public static final byte TAG_TZDataVersion = 68; - - /** - * Excluded zones item tag. (Added in Mustang) - */ - public static final byte TAG_ExcludedZones = 69; - - private static Map zoneInfoObjects = null; - - private static final ZoneInfoOld GMT = new ZoneInfoOld("GMT", 0); - - static String ziDir; - - /** - * Converts the given time zone ID to a platform dependent path - * name. For example, "America/Los_Angeles" is converted to - * "America\Los_Angeles" on Win32. - * @return a modified ID replacing '/' with {@link - * java.io.File#separatorChar File.separatorChar} if needed. - */ - public static String getFileName(String ID) { - if (File.separatorChar == '/') { - return ID; - } - return ID.replace('/', File.separatorChar); - } - - /** - * Gets a ZoneInfo with the given GMT offset. The object - * has its ID in the format of GMT{+|-}hh:mm. - * - * @param originalId the given custom id (before normalized such as "GMT+9") - * @param gmtOffset GMT offset in milliseconds - * @return a ZoneInfo constructed with the given GMT offset - */ - public static ZoneInfoOld getCustomTimeZone(String originalId, int gmtOffset) { - String id = toCustomID(gmtOffset); - - ZoneInfoOld zi = getFromCache(id); - if (zi == null) { - zi = new ZoneInfoOld(id, gmtOffset); - zi = addToCache(id, zi); - if (!id.equals(originalId)) { - zi = addToCache(originalId, zi); - } - } - return (ZoneInfoOld) zi.clone(); - } - - public static String toCustomID(int gmtOffset) { - char sign; - int offset = gmtOffset / 60000; - - if (offset >= 0) { - sign = '+'; - } else { - sign = '-'; - offset = -offset; - } - int hh = offset / 60; - int mm = offset % 60; - - char[] buf = new char[] { 'G', 'M', 'T', sign, '0', '0', ':', '0', '0' }; - if (hh >= 10) { - buf[4] += hh / 10; - } - buf[5] += hh % 10; - if (mm != 0) { - buf[7] += mm / 10; - buf[8] += mm % 10; - } - return new String(buf); - } - - /** - * @return a ZoneInfo instance created for the specified id, or - * null if there is no time zone data file found for the specified - * id. - */ - public static ZoneInfoOld getZoneInfoOld(String id) { - //treat GMT zone as special - if ("GMT".equals(id)) - return (ZoneInfoOld) GMT.clone(); - ZoneInfoOld zi = getFromCache(id); - if (zi == null) { - Map aliases = ZoneInfoOld.getCachedAliasTable(); - if (aliases != null && aliases.get(id) != null) { - return null; - } - zi = createZoneInfoOld(id); - if (zi == null) { - return null; - } - zi = addToCache(id, zi); - } - return (ZoneInfoOld) zi.clone(); - } - - synchronized static ZoneInfoOld getFromCache(String id) { - if (zoneInfoObjects == null) { - return null; - } - return zoneInfoObjects.get(id); - } - - synchronized static ZoneInfoOld addToCache(String id, ZoneInfoOld zi) { - if (zoneInfoObjects == null) { - zoneInfoObjects = new HashMap<>(); - } else { - ZoneInfoOld zone = zoneInfoObjects.get(id); - if (zone != null) { - return zone; - } - } - zoneInfoObjects.put(id, zi); - return zi; - } - - private static ZoneInfoOld createZoneInfoOld(String id) { - byte[] buf = readZoneInfoFile(getFileName(id)); - if (buf == null) { - return null; - } - - int index = 0; - int filesize = buf.length; - int rawOffset = 0; - int dstSavings = 0; - int checksum = 0; - boolean willGMTOffsetChange = false; - long[] transitions = null; - int[] offsets = null; - int[] simpleTimeZoneParams = null; - - try { - for (index = 0; index < JAVAZI_LABEL.length; index++) { - if (buf[index] != JAVAZI_LABEL[index]) { - System.err.println("ZoneInfoOld: wrong magic number: " + id); - return null; - } - } - if (buf[index++] > JAVAZI_VERSION) { - System.err.println("ZoneInfo: incompatible version (" - + buf[index - 1] + "): " + id); - return null; - } - - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - if (filesize < index+len) { - break; - } - - switch (tag) { - case TAG_CRC32: - { - int val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - checksum = val; - } - break; - - case TAG_LastDSTSaving: - { - short val = (short)(buf[index++] & 0xff); - val = (short)((val << 8) + (buf[index++] & 0xff)); - dstSavings = val * 1000; - } - break; - - case TAG_RawOffset: - { - int val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - rawOffset = val; - } - break; - - case TAG_Transition: - { - int n = len / 8; - transitions = new long[n]; - for (int i = 0; i < n; i ++) { - long val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - transitions[i] = val; - } - } - break; - - case TAG_Offset: - { - int n = len / 4; - offsets = new int[n]; - for (int i = 0; i < n; i ++) { - int val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - offsets[i] = val; - } - } - break; - - case TAG_SimpleTimeZone: - { - if (len != 32 && len != 40) { - System.err.println("ZoneInfo: wrong SimpleTimeZone parameter size"); - return null; - } - int n = len / 4; - simpleTimeZoneParams = new int[n]; - for (int i = 0; i < n; i++) { - int val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - simpleTimeZoneParams[i] = val; - } - } - break; - - case TAG_GMTOffsetWillChange: - { - if (len != 1) { - System.err.println("ZoneInfo: wrong byte length for TAG_GMTOffsetWillChange"); - } - willGMTOffsetChange = buf[index++] == 1; - } - break; - - default: - System.err.println("ZoneInfo: unknown tag < " + tag + ">. ignored."); - index += len; - break; - } - } - } catch (Exception e) { - System.err.println("ZoneInfo: corrupted zoneinfo file: " + id); - return null; - } - - if (index != filesize) { - System.err.println("ZoneInfo: wrong file size: " + id); - return null; - } - - return new ZoneInfoOld(id, rawOffset, dstSavings, checksum, - transitions, offsets, simpleTimeZoneParams, - willGMTOffsetChange); - } - - private volatile static SoftReference> zoneIDs = null; - - static List getZoneIDs() { - List ids = null; - SoftReference> cache = zoneIDs; - if (cache != null) { - ids = cache.get(); - if (ids != null) { - return ids; - } - } - byte[] buf = null; - buf = getZoneInfoOldMappings(); - int index = JAVAZM_LABEL_LENGTH + 1; - int filesize = buf.length; - try { - loop: - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - switch (tag) { - case TAG_ZoneIDs: - { - int n = (buf[index++] << 8) + (buf[index++] & 0xFF); - ids = new ArrayList<>(n); - - for (int i = 0; i < n; i++) { - byte m = buf[index++]; - ids.add(new String(buf, index, m, "UTF-8")); - index += m; - } - } - break loop; - - default: - index += len; - break; - } - } - } catch (Exception e) { - System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); - } - - zoneIDs = new SoftReference<>(ids); - return ids; - } - - /** - * @return an alias table in HashMap where a key is an alias ID - * (e.g., "PST") and its value is a real time zone ID (e.g., - * "America/Los_Angeles"). - */ - static Map getZoneAliases() { - byte[] buf = getZoneInfoOldMappings(); - int index = JAVAZM_LABEL_LENGTH + 1; - int filesize = buf.length; - Map aliases = null; - - try { - loop: - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - switch (tag) { - case TAG_ZoneAliases: - { - int n = (buf[index++] << 8) + (buf[index++] & 0xFF); - aliases = new HashMap<>(n); - for (int i = 0; i < n; i++) { - byte m = buf[index++]; - String name = new String(buf, index, m, "UTF-8"); - index += m; - m = buf[index++]; - String realName = new String(buf, index, m, "UTF-8"); - index += m; - aliases.put(name, realName); - } - } - break loop; - - default: - index += len; - break; - } - } - } catch (Exception e) { - System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); - return null; - } - return aliases; - } - - private volatile static SoftReference> excludedIDs = null; - private volatile static boolean hasNoExcludeList = false; - - /** - * @return a List of zone IDs for zones that will change their GMT - * offsets in some future time. - * - * @since 1.6 - */ - static List getExcludedZones() { - if (hasNoExcludeList) { - return null; - } - - List excludeList = null; - - SoftReference> cache = excludedIDs; - if (cache != null) { - excludeList = cache.get(); - if (excludeList != null) { - return excludeList; - } - } - - byte[] buf = getZoneInfoOldMappings(); - int index = JAVAZM_LABEL_LENGTH + 1; - int filesize = buf.length; - - try { - loop: - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - switch (tag) { - case TAG_ExcludedZones: - { - int n = (buf[index++] << 8) + (buf[index++] & 0xFF); - excludeList = new ArrayList<>(); - for (int i = 0; i < n; i++) { - byte m = buf[index++]; - String name = new String(buf, index, m, "UTF-8"); - index += m; - excludeList.add(name); - } - } - break loop; - - default: - index += len; - break; - } - } - } catch (Exception e) { - System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); - return null; - } - - if (excludeList != null) { - excludedIDs = new SoftReference<>(excludeList); - } else { - hasNoExcludeList = true; - } - return excludeList; - } - - private volatile static SoftReference rawOffsetIndices = null; - - static byte[] getRawOffsetIndices() { - byte[] indices = null; - - SoftReference cache = rawOffsetIndices; - if (cache != null) { - indices = cache.get(); - if (indices != null) { - return indices; - } - } - - byte[] buf = getZoneInfoOldMappings(); - int index = JAVAZM_LABEL_LENGTH + 1; - int filesize = buf.length; - - try { - loop: - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - switch (tag) { - case TAG_RawOffsetIndices: - { - indices = new byte[len]; - for (int i = 0; i < len; i++) { - indices[i] = buf[index++]; - } - } - break loop; - - default: - index += len; - break; - } - } - } catch (ArrayIndexOutOfBoundsException e) { - System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); - } - - rawOffsetIndices = new SoftReference<>(indices); - return indices; - } - - private volatile static SoftReference rawOffsets = null; - - static int[] getRawOffsets() { - int[] offsets = null; - - SoftReference cache = rawOffsets; - if (cache != null) { - offsets = cache.get(); - if (offsets != null) { - return offsets; - } - } - - byte[] buf = getZoneInfoOldMappings(); - int index = JAVAZM_LABEL_LENGTH + 1; - int filesize = buf.length; - - try { - loop: - while (index < filesize) { - byte tag = buf[index++]; - int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); - - switch (tag) { - case TAG_RawOffsets: - { - int n = len/4; - offsets = new int[n]; - for (int i = 0; i < n; i++) { - int val = buf[index++] & 0xff; - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - val = (val << 8) + (buf[index++] & 0xff); - offsets[i] = val; - } - } - break loop; - - default: - index += len; - break; - } - } - } catch (ArrayIndexOutOfBoundsException e) { - System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); - } - - rawOffsets = new SoftReference<>(offsets); - return offsets; - } - - private volatile static SoftReference zoneInfoMappings = null; - - private static byte[] getZoneInfoOldMappings() { - byte[] data; - SoftReference cache = zoneInfoMappings; - if (cache != null) { - data = cache.get(); - if (data != null) { - return data; - } - } - data = readZoneInfoFile(JAVAZM_FILE_NAME); - if (data == null) { - throw new RuntimeException("ZoneInfoOldMapping " + - JAVAZM_FILE_NAME + " either doesn't exist or doesn't have data"); - } - - int index; - for (index = 0; index < JAVAZM_LABEL.length; index++) { - if (data[index] != JAVAZM_LABEL[index]) { - System.err.println("ZoneInfoOld: wrong magic number: " + JAVAZM_FILE_NAME); - return null; - } - } - if (data[index++] > JAVAZM_VERSION) { - System.err.println("ZoneInfoOld: incompatible version (" - + data[index - 1] + "): " + JAVAZM_FILE_NAME); - return null; - } - - zoneInfoMappings = new SoftReference<>(data); - return data; - } - - /** - * Reads the specified file under <java.home>/lib/zi into a buffer. - * @return the buffer, or null if any I/O error occurred. - */ - private static byte[] readZoneInfoFile(final String fileName) { - if (fileName.indexOf("..") >= 0) { - return null; - } - byte[] buffer = null; - File file = new File(ziDir, fileName); - try { - int filesize = (int)file.length(); - if (filesize > 0) { - FileInputStream fis = new FileInputStream(file); - buffer = new byte[filesize]; - try { - if (fis.read(buffer) != filesize) { - throw new IOException("read error on " + fileName); - } - } finally { - fis.close(); - } - } - } catch (Exception ex) { - if (!(ex instanceof FileNotFoundException) || JAVAZM_FILE_NAME.equals(fileName)) { - System.err.println("ZoneInfoOld: " + ex.getMessage()); - } - } - return buffer; - } - - private ZoneInfoFile() { - } -} diff --git a/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java b/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java deleted file mode 100644 index 300b7f13ddd..00000000000 --- a/test/jdk/sun/util/calendar/zi/ZoneInfoOld.java +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.lang.ref.SoftReference; -import java.time.ZoneOffset; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.SimpleTimeZone; -import java.util.TimeZone; - -import sun.util.calendar.CalendarSystem; -import sun.util.calendar.CalendarDate; - -/** - * ZoneInfoOld is an implementation subclass of {@link - * java.util.TimeZone TimeZone} that represents GMT offsets and - * daylight saving time transitions of a time zone. - *

    - * The daylight saving time transitions are described in the {@link - * #transitions transitions} table consisting of a chronological - * sequence of transitions of GMT offset and/or daylight saving time - * changes. Since all transitions are represented in UTC, in theory, - * ZoneInfoOld can be used with any calendar systems except - * for the {@link #getOffset(int,int,int,int,int,int) getOffset} - * method that takes Gregorian calendar date fields. - *

    - * This table covers transitions from 1900 until 2100 (as of version - * 23), Before 1900, it assumes that there was no daylight saving - * time and the getOffset methods always return the - * {@link #getRawOffset} value. No Local Mean Time is supported. If a - * specified date is beyond the transition table and this time zone is - * supposed to observe daylight saving time in 2100, it delegates - * operations to a {@link java.util.SimpleTimeZone SimpleTimeZone} - * object created using the daylight saving time schedule as of 2100. - *

    - * The date items, transitions, GMT offset(s), etc. are read from a database - * file. See {@link ZoneInfoFile} for details. - * @see java.util.SimpleTimeZone - * @since 1.4 - */ - -public class ZoneInfoOld extends TimeZone { - - // The constants assume no leap seconds support. - static final int SECOND_IN_MILLIS = 1000; - static final int MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60; - static final int HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60; - static final int DAY_IN_MILLIS = HOUR_IN_MILLIS * 24; - - private static final int UTC_TIME = 0; - private static final int STANDARD_TIME = 1; - private static final int WALL_TIME = 2; - - private static final long OFFSET_MASK = 0x0fL; - private static final long DST_MASK = 0xf0L; - private static final int DST_NSHIFT = 4; - // this bit field is reserved for abbreviation support - private static final long ABBR_MASK = 0xf00L; - private static final int TRANSITION_NSHIFT = 12; - - // IDs having conflicting data between Olson and JDK 1.1 - static final Map conflictingIDs = Map.of( - "EST", "America/Panama", - "MST", "America/Phoenix"); - - private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar(); - - /** - * The raw GMT offset in milliseconds between this zone and GMT. - * Negative offsets are to the west of Greenwich. To obtain local - * standard time, add the offset to GMT time. - * @serial - */ - int rawOffset; - - /** - * Difference in milliseconds from the original GMT offset in case - * the raw offset value has been modified by calling {@link - * #setRawOffset}. The initial value is 0. - * @serial - */ - int rawOffsetDiff = 0; - - /** - * A CRC32 value of all pairs of transition time (in milliseconds - * in long) in local time and its GMT offset (in - * seconds in int) in the chronological order. Byte - * values of each long and int are taken - * in the big endian order (i.e., MSB to LSB). - * @serial - */ - int checksum; - - /** - * The amount of time in milliseconds saved during daylight saving - * time. If useDaylight is false, this value is 0. - * @serial - */ - int dstSavings; - - /** - * This array describes transitions of GMT offsets of this time - * zone, including both raw offset changes and daylight saving - * time changes. - * A long integer consists of four bit fields. - *

      - *
    • The most significant 52-bit field represents transition - * time in milliseconds from Gregorian January 1 1970, 00:00:00 - * GMT.
    • - *
    • The next 4-bit field is reserved and must be 0.
    • - *
    • The next 4-bit field is an index value to {@link #offsets - * offsets[]} for the amount of daylight saving at the - * transition. If this value is zero, it means that no daylight - * saving, not the index value zero.
    • - *
    • The least significant 4-bit field is an index value to - * {@link #offsets offsets[]} for total GMT offset at the - * transition.
    • - *
    - * If this time zone doesn't observe daylight saving time and has - * never changed any GMT offsets in the past, this value is null. - * @serial - */ - long[] transitions; - - /** - * This array holds all unique offset values in - * milliseconds. Index values to this array are stored in the - * transitions array elements. - * @serial - */ - int[] offsets; - - /** - * SimpleTimeZone parameter values. It has to have either 8 for - * {@link java.util.SimpleTimeZone#SimpleTimeZone(int, String, - * int, int , int , int , int , int , int , int , int) the - * 11-argument SimpleTimeZone constructor} or 10 for {@link - * java.util.SimpleTimeZone#SimpleTimeZone(int, String, int, int, - * int , int , int , int , int , int , int, int, int) the - * 13-argument SimpleTimeZone constructor} parameters. - * @serial - */ - int[] simpleTimeZoneParams; - - /** - * True if the raw GMT offset value would change after the time - * zone data has been generated; false, otherwise. The default - * value is false. - * @serial - */ - boolean willGMTOffsetChange = false; - - /** - * True if the object has been modified after its instantiation. - */ - transient private boolean dirty = false; - - private static final long serialVersionUID = 2653134537216586139L; - - /** - * A constructor. - */ - public ZoneInfoOld() { - } - - /** - * A Constructor for CustomID. - */ - public ZoneInfoOld(String ID, int rawOffset) { - this(ID, rawOffset, 0, 0, null, null, null, false); - } - - /** - * Constructs a ZoneInfoOld instance. - * - * @param ID time zone name - * @param rawOffset GMT offset in milliseconds - * @param dstSavings daylight saving value in milliseconds or 0 - * (zero) if this time zone doesn't observe Daylight Saving Time. - * @param checksum CRC32 value with all transitions table entry - * values - * @param transitions transition table - * @param offsets offset value table - * @param simpleTimeZoneParams parameter values for constructing - * SimpleTimeZone - * @param willGMTOffsetChange the value of willGMTOffsetChange - */ - ZoneInfoOld(String ID, - int rawOffset, - int dstSavings, - int checksum, - long[] transitions, - int[] offsets, - int[] simpleTimeZoneParams, - boolean willGMTOffsetChange) { - setID(ID); - this.rawOffset = rawOffset; - this.dstSavings = dstSavings; - this.checksum = checksum; - this.transitions = transitions; - this.offsets = offsets; - this.simpleTimeZoneParams = simpleTimeZoneParams; - this.willGMTOffsetChange = willGMTOffsetChange; - } - - /** - * Returns the difference in milliseconds between local time and UTC - * of given time, taking into account both the raw offset and the - * effect of daylight savings. - * - * @param date the milliseconds in UTC - * @return the milliseconds to add to UTC to get local wall time - */ - public int getOffset(long date) { - return getOffsets(date, null, UTC_TIME); - } - - public int getOffsets(long utc, int[] offsets) { - return getOffsets(utc, offsets, UTC_TIME); - } - - public int getOffsetsByStandard(long standard, int[] offsets) { - return getOffsets(standard, offsets, STANDARD_TIME); - } - - public int getOffsetsByWall(long wall, int[] offsets) { - return getOffsets(wall, offsets, WALL_TIME); - } - - private int getOffsets(long date, int[] offsets, int type) { - // if dst is never observed, there is no transition. - if (transitions == null) { - int offset = getLastRawOffset(); - if (offsets != null) { - offsets[0] = offset; - offsets[1] = 0; - } - return offset; - } - - date -= rawOffsetDiff; - int index = getTransitionIndex(date, type); - - // prior to the transition table, returns the raw offset. - // FIXME: should support LMT. - if (index < 0) { - int offset = getLastRawOffset(); - if (offsets != null) { - offsets[0] = offset; - offsets[1] = 0; - } - return offset; - } - - if (index < transitions.length) { - long val = transitions[index]; - int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff; - if (offsets != null) { - int dst = (int)((val >>> DST_NSHIFT) & 0xfL); - int save = (dst == 0) ? 0 : this.offsets[dst]; - offsets[0] = offset - save; - offsets[1] = save; - } - return offset; - } - - // beyond the transitions, delegate to SimpleTimeZone if there - // is a rule; otherwise, return rawOffset. - SimpleTimeZone tz = getLastRule(); - if (tz != null) { - int rawoffset = tz.getRawOffset(); - long msec = date; - if (type != UTC_TIME) { - msec -= rawOffset; - } - int dstoffset = tz.getOffset(msec) - rawOffset; - - // Check if it's in a standard-to-daylight transition. - if (dstoffset > 0 && tz.getOffset(msec - dstoffset) == rawoffset) { - dstoffset = 0; - } - - if (offsets != null) { - offsets[0] = rawoffset; - offsets[1] = dstoffset; - } - return rawoffset + dstoffset; - } - int offset = getLastRawOffset(); - if (offsets != null) { - offsets[0] = offset; - offsets[1] = 0; - } - return offset; - } - - private int getTransitionIndex(long date, int type) { - int low = 0; - int high = transitions.length - 1; - - while (low <= high) { - int mid = (low + high) / 2; - long val = transitions[mid]; - long midVal = val >> TRANSITION_NSHIFT; // sign extended - if (type != UTC_TIME) { - midVal += offsets[(int)(val & OFFSET_MASK)]; // wall time - } - if (type == STANDARD_TIME) { - int dstIndex = (int)((val >>> DST_NSHIFT) & 0xfL); - if (dstIndex != 0) { - midVal -= offsets[dstIndex]; // make it standard time - } - } - - if (midVal < date) { - low = mid + 1; - } else if (midVal > date) { - high = mid - 1; - } else { - return mid; - } - } - - // if beyond the transitions, returns that index. - if (low >= transitions.length) { - return low; - } - return low - 1; - } - - /** - * Returns the difference in milliseconds between local time and - * UTC, taking into account both the raw offset and the effect of - * daylight savings, for the specified date and time. This method - * assumes that the start and end month are distinct. This method - * assumes a Gregorian calendar for calculations. - *

    - * Note: In general, clients should use - * {@link Calendar#ZONE_OFFSET Calendar.get(ZONE_OFFSET)} + - * {@link Calendar#DST_OFFSET Calendar.get(DST_OFFSET)} - * instead of calling this method. - * - * @param era The era of the given date. The value must be either - * GregorianCalendar.AD or GregorianCalendar.BC. - * @param year The year in the given date. - * @param month The month in the given date. Month is 0-based. e.g., - * 0 for January. - * @param day The day-in-month of the given date. - * @param dayOfWeek The day-of-week of the given date. - * @param millis The milliseconds in day in standard local time. - * @return The milliseconds to add to UTC to get local time. - */ - public int getOffset(int era, int year, int month, int day, - int dayOfWeek, int milliseconds) { - if (milliseconds < 0 || milliseconds >= DAY_IN_MILLIS) { - throw new IllegalArgumentException(); - } - - if (era == java.util.GregorianCalendar.BC) { // BC - year = 1 - year; - } else if (era != java.util.GregorianCalendar.AD) { - throw new IllegalArgumentException(); - } - - CalendarDate date = gcal.newCalendarDate(null); - date.setDate(year, month + 1, day); - if (gcal.validate(date) == false) { - throw new IllegalArgumentException(); - } - - // bug-for-bug compatible argument checking - if (dayOfWeek < java.util.GregorianCalendar.SUNDAY - || dayOfWeek > java.util.GregorianCalendar.SATURDAY) { - throw new IllegalArgumentException(); - } - - if (transitions == null) { - return getLastRawOffset(); - } - - long dateInMillis = gcal.getTime(date) + milliseconds; - dateInMillis -= (long) rawOffset; // make it UTC - return getOffsets(dateInMillis, null, UTC_TIME); - } - - /** - * Sets the base time zone offset from GMT. This operation - * modifies all the transitions of this ZoneInfoOld object, including - * historical ones, if applicable. - * - * @param offsetMillis the base time zone offset to GMT. - * @see getRawOffset - */ - public synchronized void setRawOffset(int offsetMillis) { - if (offsetMillis == rawOffset + rawOffsetDiff) { - return; - } - rawOffsetDiff = offsetMillis - rawOffset; - if (lastRule != null) { - lastRule.setRawOffset(offsetMillis); - } - dirty = true; - } - - /** - * Returns the GMT offset of the current date. This GMT offset - * value is not modified during Daylight Saving Time. - * - * @return the GMT offset value in milliseconds to add to UTC time - * to get local standard time - */ - public int getRawOffset() { - if (!willGMTOffsetChange) { - return rawOffset + rawOffsetDiff; - } - - int[] offsets = new int[2]; - getOffsets(System.currentTimeMillis(), offsets, UTC_TIME); - return offsets[0]; - } - - public boolean isDirty() { - return dirty; - } - - int getLastRawOffset() { - return rawOffset + rawOffsetDiff; - } - - /** - * Queries if this time zone uses Daylight Saving Time in the last known rule. - */ - public boolean useDaylightTime() { - return (simpleTimeZoneParams != null); - } - - @Override - public boolean observesDaylightTime() { - if (simpleTimeZoneParams != null) { - return true; - } - if (transitions == null) { - return false; - } - - // Look up the transition table to see if it's in DST right - // now or if there's any standard-to-daylight transition at - // any future. - long utc = System.currentTimeMillis() - rawOffsetDiff; - int index = getTransitionIndex(utc, UTC_TIME); - - // before transitions in the transition table - if (index < 0) { - return false; - } - - // the time is in the table range. - for (int i = index; i < transitions.length; i++) { - if ((transitions[i] & DST_MASK) != 0) { - return true; - } - } - // No further DST is observed. - return false; - } - - /** - * Queries if the specified date is in Daylight Saving Time. - */ - public boolean inDaylightTime(Date date) { - if (date == null) { - throw new NullPointerException(); - } - - if (transitions == null) { - return false; - } - - long utc = date.getTime() - rawOffsetDiff; - int index = getTransitionIndex(utc, UTC_TIME); - - // before transitions in the transition table - if (index < 0) { - return false; - } - - // the time is in the table range. - if (index < transitions.length) { - return (transitions[index] & DST_MASK) != 0; - } - - // beyond the transition table - SimpleTimeZone tz = getLastRule(); - if (tz != null) { - return tz.inDaylightTime(date); - } - return false; - } - - /** - * Returns the amount of time in milliseconds that the clock is advanced - * during daylight saving time is in effect in its last daylight saving time rule. - * - * @return the number of milliseconds the time is advanced with respect to - * standard time when daylight saving time is in effect. - */ - public int getDSTSavings() { - return dstSavings; - } - -// /** -// * @return the last year in the transition table or -1 if this -// * time zone doesn't observe any daylight saving time. -// */ -// public int getMaxTransitionYear() { -// if (transitions == null) { -// return -1; -// } -// long val = transitions[transitions.length - 1]; -// int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff; -// val = (val >> TRANSITION_NSHIFT) + offset; -// CalendarDate lastDate = Gregorian.getCalendarDate(val); -// return lastDate.getYear(); -// } - - /** - * Returns a string representation of this time zone. - * @return the string - */ - public String toString() { - return getClass().getName() + - "[id=\"" + getID() + "\"" + - ",offset=" + getLastRawOffset() + - ",dstSavings=" + dstSavings + - ",useDaylight=" + useDaylightTime() + - ",transitions=" + ((transitions != null) ? transitions.length : 0) + - ",lastRule=" + (lastRule == null ? getLastRuleInstance() : lastRule) + - "]"; - } - - /** - * Gets all available IDs supported in the Java run-time. - * - * @return an array of time zone IDs. - */ - public static String[] getAvailableIDs() { - List idList = ZoneInfoFile.getZoneIDs(); - List excluded = ZoneInfoFile.getExcludedZones(); - if (excluded != null) { - // List all zones from the idList and excluded lists - List list = new ArrayList<>(idList.size() + excluded.size()); - list.addAll(idList); - list.addAll(excluded); - idList = list; - } - String[] ids = new String[idList.size()]; - return idList.toArray(ids); - } - - /** - * Gets all available IDs that have the same value as the - * specified raw GMT offset. - * - * @param rawOffset the GMT offset in milliseconds. This - * value should not include any daylight saving time. - * - * @return an array of time zone IDs. - */ - public static String[] getAvailableIDs(int rawOffset) { - String[] result; - List matched = new ArrayList<>(); - List IDs = ZoneInfoFile.getZoneIDs(); - int[] rawOffsets = ZoneInfoFile.getRawOffsets(); - - loop: - for (int index = 0; index < rawOffsets.length; index++) { - if (rawOffsets[index] == rawOffset) { - byte[] indices = ZoneInfoFile.getRawOffsetIndices(); - for (int i = 0; i < indices.length; i++) { - if (indices[i] == index) { - matched.add(IDs.get(i++)); - while (i < indices.length && indices[i] == index) { - matched.add(IDs.get(i++)); - } - break loop; - } - } - } - } - - // We need to add any zones from the excluded zone list that - // currently have the same GMT offset as the specified - // rawOffset. The zones returned by this method may not be - // correct as of return to the caller if any GMT offset - // transition is happening during this GMT offset checking... - List excluded = ZoneInfoFile.getExcludedZones(); - if (excluded != null) { - for (String id : excluded) { - TimeZone zi = getTimeZone(id); - if (zi != null && zi.getRawOffset() == rawOffset) { - matched.add(id); - } - } - } - - result = new String[matched.size()]; - matched.toArray(result); - return result; - } - - /** - * Gets the ZoneInfoOld for the given ID. - * - * @param ID the ID for a ZoneInfoOld. See TimeZone for detail. - * - * @return the specified ZoneInfoOld object, or null if there is no - * time zone of the ID. - */ - public static TimeZone getTimeZone(String ID) { - String givenID = null; - - ZoneInfoOld zi = ZoneInfoFile.getZoneInfoOld(ID); - if (zi == null) { - // if we can't create an object for the ID, try aliases. - try { - Map map = getAliasTable(); - String alias = ID; - while ((alias = map.get(alias)) != null) { - zi = ZoneInfoFile.getZoneInfoOld(alias); - if (zi != null) { - zi.setID(ID); - zi = ZoneInfoFile.addToCache(ID, zi); - zi = (ZoneInfoOld) zi.clone(); - break; - } - } - } catch (Exception e) { - // ignore exceptions - } - } - - if (givenID != null && zi != null) { - zi.setID(givenID); - } - return zi; - } - - private transient SimpleTimeZone lastRule; - - /** - * Returns a SimpleTimeZone object representing the last GMT - * offset and DST schedule or null if this time zone doesn't - * observe DST. - */ - synchronized SimpleTimeZone getLastRule() { - if (lastRule == null) { - lastRule = getLastRuleInstance(); - } - return lastRule; - } - - /** - * Returns a SimpleTimeZone object that represents the last - * known daylight saving time rules. - * - * @return a SimpleTimeZone object or null if this time zone - * doesn't observe DST. - */ - public SimpleTimeZone getLastRuleInstance() { - if (simpleTimeZoneParams == null) { - return null; - } - if (simpleTimeZoneParams.length == 10) { - return new SimpleTimeZone(getLastRawOffset(), getID(), - simpleTimeZoneParams[0], - simpleTimeZoneParams[1], - simpleTimeZoneParams[2], - simpleTimeZoneParams[3], - simpleTimeZoneParams[4], - simpleTimeZoneParams[5], - simpleTimeZoneParams[6], - simpleTimeZoneParams[7], - simpleTimeZoneParams[8], - simpleTimeZoneParams[9], - dstSavings); - } - return new SimpleTimeZone(getLastRawOffset(), getID(), - simpleTimeZoneParams[0], - simpleTimeZoneParams[1], - simpleTimeZoneParams[2], - simpleTimeZoneParams[3], - simpleTimeZoneParams[4], - simpleTimeZoneParams[5], - simpleTimeZoneParams[6], - simpleTimeZoneParams[7], - dstSavings); - } - - /** - * Returns a copy of this ZoneInfoOld. - */ - public Object clone() { - ZoneInfoOld zi = (ZoneInfoOld) super.clone(); - zi.lastRule = null; - return zi; - } - - /** - * Returns a hash code value calculated from the GMT offset and - * transitions. - * @return a hash code of this time zone - */ - public int hashCode() { - return getLastRawOffset() ^ checksum; - } - - /** - * Compares the equity of two ZoneInfoOld objects. - * - * @param obj the object to be compared with - * @return true if given object is same as this ZoneInfoOld object, - * false otherwise. - */ - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof ZoneInfoOld)) { - return false; - } - ZoneInfoOld that = (ZoneInfoOld) obj; - return (getID().equals(that.getID()) - && (getLastRawOffset() == that.getLastRawOffset()) - && (checksum == that.checksum)); - } - - /** - * Returns true if this zone has the same raw GMT offset value and - * transition table as another zone info. If the specified - * TimeZone object is not a ZoneInfoOld instance, this method returns - * true if the specified TimeZone object has the same raw GMT - * offset value with no daylight saving time. - * - * @param other the ZoneInfoOld object to be compared with - * @return true if the given TimeZone has the same - * GMT offset and transition information; false, otherwise. - */ - public boolean hasSameRules(TimeZone other) { - if (this == other) { - return true; - } - if (other == null) { - return false; - } - if (!(other instanceof ZoneInfoOld)) { - if (getRawOffset() != other.getRawOffset()) { - return false; - } - // if both have the same raw offset and neither observes - // DST, they have the same rule. - if ((transitions == null) - && (useDaylightTime() == false) - && (other.useDaylightTime() == false)) { - return true; - } - return false; - } - if (getLastRawOffset() != ((ZoneInfoOld)other).getLastRawOffset()) { - return false; - } - return (checksum == ((ZoneInfoOld)other).checksum); - } - - private static SoftReference> aliasTable; - - static Map getCachedAliasTable() { - Map aliases = null; - - SoftReference> cache = aliasTable; - if (cache != null) { - aliases = cache.get(); - } - return aliases; - } - - /** - * Returns a Map from alias time zone IDs to their standard - * time zone IDs. - * - * @return the Map that holds the mappings from alias time zone IDs - * to their standard time zone IDs, or null if - * ZoneInfoOldMappings file is not available. - */ - public synchronized static Map getAliasTable() { - Map aliases = getCachedAliasTable(); - if (aliases == null) { - aliases = ZoneInfoFile.getZoneAliases(); - if (aliases != null) { - // Replace old mappings from `jdk11_backward` - aliases.putAll(conflictingIDs); - aliasTable = new SoftReference>(aliases); - } - } - return aliases; - } - - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - // We don't know how this object from 1.4.x or earlier has - // been mutated. So it should always be marked as `dirty'. - dirty = true; - } - - ////////////////////////////////////////////////////////////// - public boolean equalsTo(ZoneInfoOld other) { - return (getID().equals(other.getID()) - && (getLastRawOffset() == other.getLastRawOffset()) - && (dstSavings == other.dstSavings) - && (willGMTOffsetChange == other.willGMTOffsetChange) - && (checksum == other.checksum) - && equalsTransOffsets(other) - && (Arrays.equals(simpleTimeZoneParams, other.simpleTimeZoneParams) || - getLastRule().equals(other.getLastRule()))); - } - - private boolean equalsTransOffsets(ZoneInfoOld other) { - if (transitions == null) { - return (other.transitions == null && - Arrays.equals(offsets, other.offsets)); - } - if (other.transitions == null || - transitions.length != other.transitions.length) { - return false; - } - // if offsets and other.offsets have different order - // the last 4-bit in trans are different. - for (int i = 0; i < transitions.length; i++) { - long val = transitions[i]; - int dst = (int)((val >>> DST_NSHIFT) & 0xfL); - int save = (dst == 0) ? 0 : offsets[dst] / 1000; - int off = offsets[(int)(val & OFFSET_MASK)]/1000; - long second = (val >> TRANSITION_NSHIFT)/1000; - - val = other.transitions[i]; - int dstO = (int)((val >>> DST_NSHIFT) & 0xfL); - int saveO = (dstO == 0) ? 0 : other.offsets[dstO] / 1000; - int offO = other.offsets[(int)(val & OFFSET_MASK)]/1000; - long secondO = (val >> TRANSITION_NSHIFT)/1000; - if ((dst == 0) != (dstO == 0) || save != saveO || off != offO || second != secondO) - return false; - } - return true; - } - - private int transToString(long val, int off_old, int[] offsets, StringBuilder sb) { - int dst = (int)((val >>> DST_NSHIFT) & 0xfL); - int save = (dst == 0) ? 0 : offsets[dst] / 1000; - int off = offsets[(int)(val & OFFSET_MASK)]/1000; - long second = (val >> TRANSITION_NSHIFT)/1000; - ZoneOffset offset_old = ZoneOffset.ofTotalSeconds(off_old); - ZoneOffset offset = ZoneOffset.ofTotalSeconds(off); - sb.append(" " + LocalDateTime.ofEpochSecond(second, 0, offset_old)); - - sb.append(" [utc=" + second + - " raw=" + Long.toHexString(val >> TRANSITION_NSHIFT) + - ", offset=" + off + "/" + offset + ", saving=" + save + "]"); - return off; - } - - public String diffsTo(ZoneInfoOld other) { - - int rawOffset0 = other.rawOffset; - int checksum0 = other.checksum; - int dstSavings0 = other.dstSavings; - long[] transitions0 = other.transitions; - int[] offsets0 = other.offsets; - int[] simpleTimeZoneParams0 = other.simpleTimeZoneParams; - boolean willGMTOffsetChange0 = other.willGMTOffsetChange; - - - //return getClass().getName() + - StringBuilder sb = new StringBuilder(); - sb.append("******************************\n" + - getID() + " : " + other.getID()); - // ROC is excluded by ZoneInfoOld - if ("ROC".equals(getID())) { - return sb.toString(); - } - if (rawOffset != rawOffset0 || - dstSavings != dstSavings0 || - checksum != checksum0 || - willGMTOffsetChange != willGMTOffsetChange0 || - (simpleTimeZoneParams != null ) != (simpleTimeZoneParams0 != null) || - (transitions != null && transitions0 != null && - transitions.length != transitions0.length)) - { - sb.append("\n offset=" + getLastRawOffset() + - ",dstSavings=" + dstSavings + - ",useDaylight=" + useDaylightTime() + - ",transitions=" + ((transitions != null) ? transitions.length : 0) + - ",offsets=" + ((offsets != null) ? offsets.length : 0) + - ",checksum=" + checksum + - ",gmtChanged=" + willGMTOffsetChange) - .append("\n[NG]offset=" + rawOffset0 + - ",dstSavings=" + dstSavings0 + - ",useDaylight=" + (simpleTimeZoneParams != null) + - ",transitions=" + ((transitions0 != null) ? transitions0.length : 0) + - ",offsets=" + ((offsets0 != null) ? offsets0.length : 0) + - ",checksum=" + checksum0 + - ",gmtChanged=" + willGMTOffsetChange0 + - ""); - } - // offsets - if (!Arrays.equals(offsets, offsets0)) { - sb.append("\n offset.len=" + ((offsets != null)? offsets.length : "null") + - " " + ((offsets0 != null)? offsets0.length : "null")); - if (offsets != null && offsets0.length != 0) { - int len = Math.min(offsets.length, offsets0.length); - int i = 0; - for (i = 0; i < len; i++) { - sb.append("\n " + - ZoneOffset.ofTotalSeconds(offsets[i]/1000) + " " + - ZoneOffset.ofTotalSeconds(offsets0[i]/1000)); - } - for (; i < offsets0.length; i++) { - sb.append("\n " + ZoneOffset.ofTotalSeconds(offsets0[i]/1000)); - } - } - } - // trans - int offset = 0; - int offset0 = 0; - if (!equalsTransOffsets(other)) { - sb.append("\n -------------"); - if ((transitions == null) != (transitions0 == null)) { - sb.append("\n (NG) Different trans(null) :" + - transitions + ", " + transitions0); - if (transitions != null) { - for (int i = 0; i < transitions.length; i++) { - sb.append("\n (NG)"); - offset = transToString(transitions[i], offset, offsets, sb); - } - } - } else { - if (transitions.length != transitions0.length) { - sb.append("\n (NG) Different trans size :" + - transitions.length + ", " + transitions0.length); - } - int length = Math.min(transitions.length, transitions0.length); - for (int i = 0; i < length; i++) { - // sb.append("\n[" + i + "] "); - // offset = transToString(transitions[i], offset, offsets, sb); - long val = transitions[i]; - int dst = (int)((val >>> DST_NSHIFT) & 0xfL); - int save = (dst == 0) ? 0 : offsets[dst] / 1000; - int off = offsets[(int)(val & OFFSET_MASK)]/1000; - long second = (val >> TRANSITION_NSHIFT)/1000; - sb.append("\n "); - offset = transToString(transitions[i], offset, offsets, sb); - if (transitions0 == null || i >= transitions0.length) { - sb.append("\n "); - offset = transToString(transitions[i], offset, offsets, sb); - sb.append("\n (NG) trans0 is null or < trans.length"); - } else { - long val0 = transitions0[i]; - int dst0 = (int)((val0 >>> DST_NSHIFT) & 0xfL); - int save0 = (dst0 == 0) ? 0 : offsets0[dst0] / 1000; - int off0 = offsets0[(int)(val0 & OFFSET_MASK)]/1000; - long second0 = (val0 >> TRANSITION_NSHIFT)/1000; - if (save != save0 || off != off0 || second != second0) { - sb.append("\n (NG)"); - } else { - sb.append("\n (OK)"); - } - offset0 = transToString(transitions0[i], offset0, offsets0, sb); - sb.append("\n -----"); - } - } - } - } - SimpleTimeZone stz = getLastRuleInstance(); - if (stz != null) { - SimpleTimeZone stz0 = other.getLastRule(); - if (!stz.hasSameRules(stz0)) { - sb.append("\n -------------") - .append("\n SimpleTimeZone (NG)") - .append("\n stz=" + stz) - .append("\n stz0=" + stz0); - } - } - sb.append("\n -------------"); - return sb.toString(); - } -} diff --git a/test/jdk/sun/util/calendar/zi/ZoneRec.java b/test/jdk/sun/util/calendar/zi/ZoneRec.java deleted file mode 100644 index f6bbeb3a199..00000000000 --- a/test/jdk/sun/util/calendar/zi/ZoneRec.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; - -/** - * ZoneRec hold information of time zone corresponding to each text - * line of the "Zone" part. - * - * @since 1.4 - */ -class ZoneRec { - private int gmtOffset; - private String ruleName; - private int directSave; - private Rule ruleRef; - private String format; - private boolean hasUntil; - private int untilYear; - private Month untilMonth; - private RuleDay untilDay; - private Time untilTime; - private long untilInMillis; - private String line; - - /** - * @return the "UNTIL" value in milliseconds - */ - Time getUntilTime() { - return untilTime; - } - - /** - * @return the GMT offset value in milliseconds - */ - int getGmtOffset() { - return gmtOffset; - } - - /** - * @return the rule name to which this zone record refers - */ - String getRuleName() { - return ruleName; - } - - /** - * @return the amount of saving time directly defined in the - * "RULES/SAVE" field. - */ - int getDirectSave() { - return directSave; - } - - /** - * @return true if this zone record has a reference to a rule - */ - boolean hasRuleReference() { - return ruleRef != null; - } - - /** - * Returns the "FORMAT" field string of this zone record. This - * @return the "FORMAT" field - */ - String getFormat() { - return format; - } - - /** - * @return the year in the "UNTIL" field - */ - int getUntilYear() { - return untilYear; - } - - /** - * Returns the "UNTIL" field value in milliseconds from Janurary - * 1, 1970 0:00 GMT. - * @param currentSave the amount of daylight saving in - * milliseconds that is used to adjust wall-clock time. - * @return the milliseconds value of the "UNTIL" field - */ - long getUntilTime(int currentSave) { - if (untilTime.isWall()) { - return untilInMillis - currentSave; - } - return untilInMillis; - } - - /** - * Returns the "UNTIL" time in milliseconds without adjusting GMT - * offsets or daylight saving. - * @return local "UNTIL" time in milliseconds - */ - long getLocalUntilTime() { - return Time.getLocalTime(untilYear, - untilMonth, - untilDay, - untilTime.getTime()); - } - - /** - * Returns the "UNTIL" time in milliseconds with adjusting GMT offsets and daylight saving. - * @return the "UNTIL" time after the adjustment - */ - long getLocalUntilTime(int save, int gmtOffset) { - return Time.getLocalTime(untilYear, - untilMonth, - untilDay, - save, - gmtOffset, - untilTime); - } - - /** - * @return the text line of this zone record - */ - String getLine() { - return line; - } - - /** - * Sets the specified text line to this zone record - */ - void setLine(String line) { - this.line = line; - } - - /** - * @return true if this zone record has the "UNTIL" field - */ - boolean hasUntil() { - return this.hasUntil; - } - - /** - * Adjusts the "UNTIL" time to GMT offset if this zone record has - * it. untilTime is not adjusted to daylight saving - * in this method. - */ - void adjustTime() { - if (!hasUntil()) { - return; - } - if (untilTime.isSTD() || untilTime.isWall()) { - // adjust to gmt offset only here. adjust to real - // wall-clock time when tracking rules - untilInMillis -= gmtOffset; - } - } - - /** - * @return the reference to the Rule object - */ - Rule getRuleRef() { - return ruleRef; - } - - /** - * Resolves the reference to a Rule and adjusts its "UNTIL" time - * to GMT offset. - */ - void resolve(Zoneinfo zi) { - if (ruleName != null && (!"-".equals(ruleName))) { - ruleRef = zi.getRule(ruleName); - } - adjustTime(); - } - - /** - * Parses a Zone text line that is described by a StringTokenizer. - * @param tokens represents tokens of a Zone text line - * @return the zone record produced by parsing the text - */ - static ZoneRec parse(StringTokenizer tokens) { - ZoneRec rec = new ZoneRec(); - try { - rec.gmtOffset = (int) Time.parse(tokens.nextToken()).getTime(); - String token = tokens.nextToken(); - char c = token.charAt(0); - if (c >= '0' && c <= '9') { - rec.directSave = (int) Time.parse(token).getTime(); - } else { - rec.ruleName = token; - } - rec.format = tokens.nextToken(); - if (tokens.hasMoreTokens()) { - rec.hasUntil = true; - rec.untilYear = Integer.parseInt(tokens.nextToken()); - if (tokens.hasMoreTokens()) { - rec.untilMonth = Month.parse(tokens.nextToken()); - } else { - rec.untilMonth = Month.JANUARY; - } - if (tokens.hasMoreTokens()) { - rec.untilDay = RuleDay.parse(tokens.nextToken()); - } else { - rec.untilDay = new RuleDay(1); - } - if (tokens.hasMoreTokens()) { - rec.untilTime = Time.parse(tokens.nextToken()); - } else { - rec.untilTime = Time.parse("0:00"); - } - rec.untilInMillis = rec.getLocalUntilTime(); - } - } catch (Exception e) { - // TODO: error reporting - e.printStackTrace(); - } - return rec; - } - - private static void panic(String msg) { - Main.panic(msg); - } -} diff --git a/test/jdk/sun/util/calendar/zi/Zoneinfo.java b/test/jdk/sun/util/calendar/zi/Zoneinfo.java deleted file mode 100644 index e125ad2cb87..00000000000 --- a/test/jdk/sun/util/calendar/zi/Zoneinfo.java +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -/** - * Zoneinfo provides javazic compiler front-end functionality. - * @since 1.4 - */ -class Zoneinfo { - - private static final int minYear = 1900; - private static final int maxYear = 2100; - private static final long minTime = Time.getLocalTime(minYear, Month.JANUARY, 1, 0); - private static int startYear = minYear; - private static int endYear = maxYear; - - /** - * True if javazic should generate a list of SimpleTimeZone - * instances for the SimpleTimeZone-based time zone support. - */ - static boolean isYearForTimeZoneDataSpecified = false; - - /** - * Zone name to Zone mappings - */ - private Map zones; - - /** - * Rule name to Rule mappings - */ - private Map rules; - - /** - * Alias name to real name mappings - */ - private Map aliases; - - /** - * Constracts a Zoneinfo. - */ - Zoneinfo() { - zones = new HashMap(); - rules = new HashMap(); - aliases = new HashMap(); - } - - /** - * Adds the given zone to the list of Zones. - * @param zone Zone to be added to the list. - */ - void add(Zone zone) { - String name = zone.getName(); - zones.put(name, zone); - } - - /** - * Adds the given rule to the list of Rules. - * @param rule Rule to be added to the list. - */ - void add(Rule rule) { - String name = rule.getName(); - rules.put(name, rule); - } - - /** - * Puts the specifid name pair to the alias table. - * @param name1 an alias time zone name - * @param name2 the real time zone of the alias name - */ - void putAlias(String name1, String name2) { - aliases.put(name1, name2); - } - - /** - * Sets the given year for SimpleTimeZone list output. - * This method is called when the -S option is specified. - * @param year the year for which SimpleTimeZone list should be generated - */ - static void setYear(int year) { - setStartYear(year); - setEndYear(year); - isYearForTimeZoneDataSpecified = true; - } - - /** - * Sets the start year. - * @param year the start year value - * @throws IllegalArgumentException if the specified year value is - * smaller than the minimum year or greater than the end year. - */ - static void setStartYear(int year) { - if (year < minYear || year > endYear) { - throw new IllegalArgumentException("invalid start year specified: " + year); - } - startYear = year; - } - - /** - * @return the start year value - */ - static int getStartYear() { - return startYear; - } - - /** - * Sets the end year. - * @param year the end year value - * @throws IllegalArgumentException if the specified year value is - * smaller than the start year or greater than the maximum year. - */ - static void setEndYear(int year) { - if (year < startYear || year > maxYear) { - throw new IllegalArgumentException(); - } - endYear = year; - } - - /** - * @return the end year value - */ - static int getEndYear() { - return endYear; - } - - /** - * @return the minimum year value - */ - static int getMinYear() { - return minYear; - } - - /** - * @return the maximum year value - */ - static int getMaxYear() { - return maxYear; - } - - /** - * @return the alias table - */ - Map getAliases() { - return aliases; - } - - /** - * @return the Zone list - */ - Map getZones() { - return zones; - } - - /** - * @return a Zone specified by name. - * @param name a zone name - */ - Zone getZone(String name) { - return zones.get(name); - } - - /** - * @return a Rule specified by name. - * @param name a rule name - */ - Rule getRule(String name) { - return rules.get(name); - } - - private static String line; - - private static int lineNum; - - /** - * Parses the specified time zone data file and creates a Zoneinfo - * that has all Rules, Zones and Links (aliases) information. - * @param fname the time zone data file name - * @return a Zoneinfo object - */ - static Zoneinfo parse(String fname) { - BufferedReader in = null; - try { - FileReader fr = new FileReader(fname); - in = new BufferedReader(fr); - } catch (FileNotFoundException e) { - panic("can't open file: "+fname); - } - Zoneinfo zi = new Zoneinfo(); - boolean continued = false; - Zone zone = null; - String l; - lineNum = 0; - - try { - while ((line = in.readLine()) != null) { - lineNum++; - // skip blank and comment lines - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - - // trim trailing comments - int rindex = line.lastIndexOf('#'); - if (rindex != -1) { - // take the data part of the line - l = line.substring(0, rindex); - } else { - l = line; - } - - StringTokenizer tokens = new StringTokenizer(l); - if (!tokens.hasMoreTokens()) { - continue; - } - String token = tokens.nextToken(); - int len = token.length(); - - if (continued || token.regionMatches(true, 0, "Zone", 0, len)){ - if (zone == null) { - if (!tokens.hasMoreTokens()) { - panic("syntax error: zone no more token"); - } - token = tokens.nextToken(); - // if the zone name is in "GMT+hh" or "GMT-hh" - // format, ignore it due to spec conflict. - if (token.startsWith("GMT+") || token.startsWith("GMT-")) { - continue; - } - zone = new Zone(token); - } else { - // no way to push the current token back... - tokens = new StringTokenizer(l); - } - - ZoneRec zrec = ZoneRec.parse(tokens); - zrec.setLine(line); - zone.add(zrec); - if ((continued = zrec.hasUntil()) == false) { - if (Zone.isTargetZone(zone.getName())) { - // zone.resolve(zi); - zi.add(zone); - } - zone = null; - } - } else if (token.regionMatches(true, 0, "Rule", 0, len)) { - if (!tokens.hasMoreTokens()) { - panic("syntax error: rule no more token"); - } - token = tokens.nextToken(); - Rule rule = zi.getRule(token); - if (rule == null) { - rule = new Rule(token); - zi.add(rule); - } - RuleRec rrec = RuleRec.parse(tokens); - rrec.setLine(line); - rule.add(rrec); - } else if (token.regionMatches(true, 0, "Link", 0, len)) { - // Link - try { - String name1 = tokens.nextToken(); - String name2 = tokens.nextToken(); - - // if the zone name is in "GMT+hh" or "GMT-hh" - // format, ignore it due to spec conflict with - // custom time zones. Also, ignore "ROC" for - // PC-ness. - if (name2.startsWith("GMT+") || name2.startsWith("GMT-") - || "ROC".equals(name2)) { - continue; - } - zi.putAlias(name2, name1); - } catch (Exception e) { - panic("syntax error: no more token for Link"); - } - } - } - in.close(); - } catch (IOException ex) { - panic("IO error: " + ex.getMessage()); - } - - return zi; - } - - /** - * Interprets a zone and constructs a Timezone object that - * contains enough information on GMT offsets and DST schedules to - * generate a zone info database. - * - * @param zoneName the zone name for which a Timezone object is - * constructed. - * - * @return a Timezone object that contains all GMT offsets and DST - * rules information. - */ - Timezone phase2(String zoneName) { - Timezone tz = new Timezone(zoneName); - Zone zone = getZone(zoneName); - zone.resolve(this); - - // TODO: merge phase2's for the regular and SimpleTimeZone ones. - if (isYearForTimeZoneDataSpecified) { - ZoneRec zrec = zone.get(zone.size()-1); - tz.setLastZoneRec(zrec); - tz.setRawOffset(zrec.getGmtOffset()); - if (zrec.hasRuleReference()) { - /* - * This part assumes that the specified year is covered by - * the rules referred to by the last zone record. - */ - List rrecs = zrec.getRuleRef().getRules(startYear); - - if (rrecs.size() == 2) { - // make sure that one is a start rule and the other is - // an end rule. - RuleRec r0 = rrecs.get(0); - RuleRec r1 = rrecs.get(1); - if (r0.getSave() == 0 && r1.getSave() > 0) { - rrecs.set(0, r1); - rrecs.set(1, r0); - } else if (!(r0.getSave() > 0 && r1.getSave() == 0)) { - rrecs = null; - Main.error(zoneName + ": rules for " + startYear + " not found."); - } - } else { - rrecs = null; - } - if (rrecs != null) { - tz.setLastRules(rrecs); - } - } - return tz; - } - - int gmtOffset; - int year = minYear; - int fromYear = year; - long fromTime = Time.getLocalTime(startYear, - Month.JANUARY, - 1, 0); - - // take the index 0 for the GMT offset of the last zone record - ZoneRec zrec = zone.get(zone.size()-1); - tz.getOffsetIndex(zrec.getGmtOffset()); - - int lastGmtOffsetValue = -1; - ZoneRec prevzrec = null; - int currentSave = 0; - boolean usedZone; - for (int zindex = 0; zindex < zone.size(); zindex++) { - zrec = zone.get(zindex); - usedZone = false; - gmtOffset = zrec.getGmtOffset(); - int stdOffset = zrec.getDirectSave(); - - if (gmtOffset != lastGmtOffsetValue) { - tz.setRawOffset(gmtOffset, fromTime); - lastGmtOffsetValue = gmtOffset; - } - // If this is the last zone record, take the last rule info. - if (!zrec.hasUntil()) { - if (zrec.hasRuleReference()) { - tz.setLastRules(zrec.getRuleRef().getLastRules()); - } else if (stdOffset != 0) { - // in case the last rule is all year round DST-only - // (Asia/Amman once announced this rule.) - tz.setLastDSTSaving(stdOffset); - } - } - if (!zrec.hasRuleReference()) { - if (!zrec.hasUntil() || zrec.getUntilTime(stdOffset) >= fromTime) { - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+stdOffset), - tz.getDstOffsetIndex(stdOffset)); - usedZone = true; - } - currentSave = stdOffset; - // optimization in case the last rule is fixed. - if (!zrec.hasUntil()) { - if (tz.getNTransitions() > 0) { - if (stdOffset == 0) { - tz.setDSTType(Timezone.X_DST); - } else { - tz.setDSTType(Timezone.LAST_DST); - } - long time = Time.getLocalTime(maxYear, - Month.JANUARY, 1, 0); - time -= zrec.getGmtOffset(); - tz.addTransition(time, - tz.getOffsetIndex(gmtOffset+stdOffset), - tz.getDstOffsetIndex(stdOffset)); - tz.addUsedRec(zrec); - } else { - tz.setDSTType(Timezone.NO_DST); - } - break; - } - } else { - Rule rule = zrec.getRuleRef(); - boolean fromTimeUsed = false; - currentSave = 0; - year_loop: - for (year = getMinYear(); year <= endYear; year++) { - if (zrec.hasUntil() && year > zrec.getUntilYear()) { - break; - } - List rules = rule.getRules(year); - if (rules.size() > 0) { - for (int i = 0; i < rules.size(); i++) { - RuleRec rrec = rules.get(i); - long transition = rrec.getTransitionTime(year, - gmtOffset, - currentSave); - if (zrec.hasUntil()) { - if (transition >= zrec.getUntilTime(currentSave)) { - // If the GMT offset changed from the previous one, - // record fromTime as a transition. - if (!fromTimeUsed && prevzrec != null - && gmtOffset != prevzrec.getGmtOffset()) { - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - fromTimeUsed = true; // for consistency - } - break year_loop; - } - } - - if (fromTimeUsed == false) { - if (fromTime <= transition) { - fromTimeUsed = true; - - if (fromTime != minTime) { - int prevsave; - - // See if until time in the previous - // ZoneRec is the same thing as the - // local time in the next rule. - // (examples are Asia/Ashkhabad in 1991, - // Europe/Riga in 1989) - - if (i > 0) { - prevsave = rules.get(i-1).getSave(); - } else { - List prevrules = rule.getRules(year-1); - - if (prevrules.size() > 0) { - prevsave = prevrules.get(prevrules.size()-1).getSave(); - } else { - prevsave = 0; - } - } - - if (rrec.isSameTransition(prevzrec, prevsave, gmtOffset)) { - currentSave = rrec.getSave(); - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - tz.addUsedRec(rrec); - usedZone = true; - continue; - } - if (!prevzrec.hasRuleReference() - || rule != prevzrec.getRuleRef() - || (rule == prevzrec.getRuleRef() - && gmtOffset != prevzrec.getGmtOffset())) { - int save = (fromTime == transition) ? rrec.getSave() : currentSave; - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - tz.addUsedRec(rrec); - usedZone = true; - } - } else { // fromTime == minTime - int save = rrec.getSave(); - tz.addTransition(minTime, - tz.getOffsetIndex(gmtOffset), - tz.getDstOffsetIndex(0)); - - tz.addTransition(transition, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - - tz.addUsedRec(rrec); - usedZone = true; - } - } else if (year == fromYear && i == rules.size()-1) { - int save = rrec.getSave(); - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - } - } - - currentSave = rrec.getSave(); - if (fromTime < transition) { - tz.addTransition(transition, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - tz.addUsedRec(rrec); - usedZone = true; - } - } - } else { - if (year == fromYear) { - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - fromTimeUsed = true; - } - if (year == endYear && !zrec.hasUntil()) { - if (tz.getNTransitions() > 0) { - // Assume that this Zone stopped DST - tz.setDSTType(Timezone.X_DST); - long time = Time.getLocalTime(maxYear, Month.JANUARY, - 1, 0); - time -= zrec.getGmtOffset(); - tz.addTransition(time, - tz.getOffsetIndex(gmtOffset), - tz.getDstOffsetIndex(0)); - usedZone = true; - } else { - tz.setDSTType(Timezone.NO_DST); - } - } - } - } - } - if (usedZone) { - tz.addUsedRec(zrec); - } - if (zrec.hasUntil() && zrec.getUntilTime(currentSave) > fromTime) { - fromTime = zrec.getUntilTime(currentSave); - fromYear = zrec.getUntilYear(); - year = zrec.getUntilYear(); - } - prevzrec = zrec; - } - - if (tz.getDSTType() == Timezone.UNDEF_DST) { - tz.setDSTType(Timezone.DST); - } - tz.optimize(); - tz.checksum(); - return tz; - } - - private static void panic(String msg) { - Main.panic(msg); - } -} diff --git a/test/jdk/sun/util/calendar/zi/tzdata_jdk/jdk11_backward b/test/jdk/sun/util/calendar/zi/tzdata_jdk/jdk11_backward deleted file mode 100644 index e480a0083be..00000000000 --- a/test/jdk/sun/util/calendar/zi/tzdata_jdk/jdk11_backward +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# JDK 1.1.x compatible time zone IDs -# - -Link Australia/Darwin ACT -Link Australia/Sydney AET -Link America/Argentina/Buenos_Aires AGT -Link Africa/Cairo ART -Link America/Anchorage AST -Link America/Sao_Paulo BET -Link Asia/Dhaka BST -Link Africa/Harare CAT -Link America/St_Johns CNT -Link America/Chicago CST -Link Asia/Shanghai CTT -Link Africa/Addis_Ababa EAT -Link Europe/Paris ECT -Link America/New_York EST -Link Pacific/Honolulu HST -Link America/Indianapolis IET -Link Asia/Calcutta IST -Link Asia/Tokyo JST -Link Pacific/Apia MIT -Link America/Denver MST -Link Asia/Yerevan NET -Link Pacific/Auckland NST -Link Asia/Karachi PLT -Link America/Phoenix PNT -Link America/Puerto_Rico PRT -Link America/Los_Angeles PST -Link Pacific/Guadalcanal SST -Link Asia/Saigon VST - -# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -Rule SystemV min 1973 - Apr lastSun 2:00 1:00 D -Rule SystemV min 1973 - Oct lastSun 2:00 0 S -Rule SystemV 1974 only - Jan 6 2:00 1:00 D -Rule SystemV 1974 only - Nov lastSun 2:00 0 S -Rule SystemV 1975 only - Feb 23 2:00 1:00 D -Rule SystemV 1975 only - Oct lastSun 2:00 0 S -Rule SystemV 1976 max - Apr lastSun 2:00 1:00 D -Rule SystemV 1976 max - Oct lastSun 2:00 0 S - -# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL] -Zone SystemV/AST4ADT -4:00 SystemV A%sT -Zone SystemV/EST5EDT -5:00 SystemV E%sT -Zone SystemV/CST6CDT -6:00 SystemV C%sT -Zone SystemV/MST7MDT -7:00 SystemV M%sT -Zone SystemV/PST8PDT -8:00 SystemV P%sT -Zone SystemV/YST9YDT -9:00 SystemV Y%sT -Zone SystemV/AST4 -4:00 - AST -Zone SystemV/EST5 -5:00 - EST -Zone SystemV/CST6 -6:00 - CST -Zone SystemV/MST7 -7:00 - MST -Zone SystemV/PST8 -8:00 - PST -Zone SystemV/YST9 -9:00 - YST -Zone SystemV/HST10 -10:00 - HST diff --git a/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java b/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java index 827f7da624d..1ffe1240d07 100644 --- a/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java +++ b/test/jdk/tools/jlink/runtimeImage/AddOptionsTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m AddOptionsTest + * @run main/othervm -Xmx1g AddOptionsTest */ public class AddOptionsTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java b/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java index ebf5b060665..b0d2a2d66f5 100644 --- a/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java +++ b/test/jdk/tools/jlink/runtimeImage/BasicJlinkMissingJavaBase.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m BasicJlinkMissingJavaBase + * @run main/othervm -Xmx1g BasicJlinkMissingJavaBase */ public class BasicJlinkMissingJavaBase extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java index 8cbd74e5ed1..b97ebff9b49 100644 --- a/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/BasicJlinkTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m BasicJlinkTest false + * @run main/othervm -Xmx1g BasicJlinkTest false */ public class BasicJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java index d6c237a173b..369bccfecfc 100644 --- a/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/CustomModuleJlinkTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m CustomModuleJlinkTest + * @run main/othervm -Xmx1g CustomModuleJlinkTest */ public class CustomModuleJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java b/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java index e59d18bd6f0..533a8db30d0 100644 --- a/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java +++ b/test/jdk/tools/jlink/runtimeImage/GenerateJLIClassesTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m GenerateJLIClassesTest + * @run main/othervm -Xmx1g GenerateJLIClassesTest */ public class GenerateJLIClassesTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java b/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java index a376d075ecd..d923358aed9 100644 --- a/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java +++ b/test/jdk/tools/jlink/runtimeImage/JavaSEReproducibleTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m JavaSEReproducibleTest + * @run main/othervm -Xmx1g JavaSEReproducibleTest */ public class JavaSEReproducibleTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java b/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java index 6fdaf5a9824..8094579ecd5 100644 --- a/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java +++ b/test/jdk/tools/jlink/runtimeImage/KeepPackagedModulesFailTest.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m KeepPackagedModulesFailTest + * @run main/othervm -Xmx1g KeepPackagedModulesFailTest */ public class KeepPackagedModulesFailTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java index 777ce302ce7..443cbbaec3c 100644 --- a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java +++ b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesExitTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m ModifiedFilesExitTest + * @run main/othervm -Xmx1g ModifiedFilesExitTest */ public class ModifiedFilesExitTest extends ModifiedFilesTest { diff --git a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java index c871024f37c..619c67e01b4 100644 --- a/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java +++ b/test/jdk/tools/jlink/runtimeImage/ModifiedFilesWarningTest.java @@ -39,7 +39,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m ModifiedFilesWarningTest + * @run main/othervm -Xmx1g ModifiedFilesWarningTest */ public class ModifiedFilesWarningTest extends ModifiedFilesTest { diff --git a/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java b/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java index 0e2cabe7425..88f91f238bd 100644 --- a/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java +++ b/test/jdk/tools/jlink/runtimeImage/MultiHopTest.java @@ -40,7 +40,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m MultiHopTest + * @run main/othervm -Xmx1g MultiHopTest */ public class MultiHopTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java b/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java index d276e80702b..ef7030d2e62 100644 --- a/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/PackagedModulesVsRuntimeImageLinkTest.java @@ -49,7 +49,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm/timeout=1200 -Xmx1400m PackagedModulesVsRuntimeImageLinkTest + * @run main/othervm/timeout=1200 -Xmx1g PackagedModulesVsRuntimeImageLinkTest */ public class PackagedModulesVsRuntimeImageLinkTest extends AbstractLinkableRuntimeTest { @@ -76,7 +76,6 @@ void runTest(Helper helper, boolean isLinkableRuntime) throws Exception { .output(helper.createNewImageDir("java-se-jmodfull")) .addMods("java.se").call().assertSuccess(); - System.out.println("Now comparing jmod-less and jmod-full) images"); compareRecursively(javaSEruntimeLink, javaSEJmodFull); } diff --git a/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java b/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java index d4654ec98bd..81579e0754b 100644 --- a/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java +++ b/test/jdk/tools/jlink/runtimeImage/PatchedJDKModuleJlinkTest.java @@ -42,7 +42,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m PatchedJDKModuleJlinkTest + * @run main/othervm -Xmx1g PatchedJDKModuleJlinkTest */ public class PatchedJDKModuleJlinkTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java index d0a6234eec0..fac8cac112d 100644 --- a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java +++ b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest.java @@ -41,7 +41,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m SystemModulesTest + * @run main/othervm -Xmx1g SystemModulesTest */ public class SystemModulesTest extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java index ee22a55f3a7..6be4ad7321c 100644 --- a/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java +++ b/test/jdk/tools/jlink/runtimeImage/SystemModulesTest2.java @@ -42,7 +42,7 @@ * jdk.jlink/jdk.tools.jimage * @build tests.* jdk.test.lib.process.OutputAnalyzer * jdk.test.lib.process.ProcessTools - * @run main/othervm -Xmx1400m SystemModulesTest2 + * @run main/othervm -Xmx1g SystemModulesTest2 */ public class SystemModulesTest2 extends AbstractLinkableRuntimeTest { diff --git a/test/jdk/tools/jpackage/windows/WinLongPathTest.java b/test/jdk/tools/jpackage/windows/WinLongPathTest.java index e9e5ef8ce03..10e713f02a8 100644 --- a/test/jdk/tools/jpackage/windows/WinLongPathTest.java +++ b/test/jdk/tools/jpackage/windows/WinLongPathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -30,6 +30,7 @@ import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Executor; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.RunnablePackageTest.Action; import jdk.jpackage.test.TKit; @@ -39,8 +40,10 @@ * @bug 8289771 * @summary jpackage with long paths on windows * @library /test/jdk/tools/jpackage/helpers + * @library /test/lib * @key jpackagePlatformPackage * @build jdk.jpackage.test.* + * @build jtreg.SkippedException * @requires (os.family == "windows") * @compile WinLongPathTest.java * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main @@ -64,6 +67,8 @@ public static List input() { @Test public void test() throws IOException { + verifyDosNamesSupported(); + if (appImage) { var cmd = JPackageCommand.helloAppImage(); setOptionLongPath(cmd, optionName); @@ -84,4 +89,23 @@ private static void setOptionLongPath(JPackageCommand cmd, String option) throws Files.createDirectories(longPath); cmd.setArgumentValue(option, longPath); } + + private static void verifyDosNamesSupported() throws IOException { + // Pick the file's name long enough to make Windows shorten it. + final var probeDosNameFile = TKit.createTempFile(Path.of("probeDosName")); + + // The output should be a DOS variant of the `probeDosNameFile` path. + // The filename should differ if the volume owning `probeDosNameFile` file supports DOS names. + final var dosPath = new Executor() + .addArguments("/c", String.format("for %%P in (\"%s\") do @echo %%~sP", probeDosNameFile)) + .setExecutable("cmd") + .dumpOutput() + .executeAndGetFirstLineOfOutput(); + + if (Path.of(dosPath).getFileName().equals(probeDosNameFile.getFileName())) { + TKit.throwSkippedException(String.format("The volume %s owning the test work directory doesn't support DOS paths", + probeDosNameFile.toAbsolutePath().getRoot())); + } + } + } diff --git a/test/langtools/tools/javac/6734819/T6734819a.out b/test/langtools/tools/javac/6734819/T6734819a.out index a3ccb07e67e..c29dbde637b 100644 --- a/test/langtools/tools/javac/6734819/T6734819a.out +++ b/test/langtools/tools/javac/6734819/T6734819a.out @@ -1,9 +1,12 @@ [attribute Y] [flow Y] +[warn Y] [attribute W] [flow W] +[warn W] [attribute Z] [flow Z] +[warn Z] [desugar Z] [desugar W] [desugar Y] diff --git a/test/langtools/tools/javac/6734819/T6734819b.out b/test/langtools/tools/javac/6734819/T6734819b.out index 0c9629006df..61c1f31f179 100644 --- a/test/langtools/tools/javac/6734819/T6734819b.out +++ b/test/langtools/tools/javac/6734819/T6734819b.out @@ -1,7 +1,9 @@ [attribute A] [flow A] +[warn A] [attribute B] [flow B] +[warn B] [desugar B] [desugar A] [generate code A] diff --git a/test/langtools/tools/javac/6734819/T6734819c.out b/test/langtools/tools/javac/6734819/T6734819c.out index 1d4cff3212f..6ae56176acb 100644 --- a/test/langtools/tools/javac/6734819/T6734819c.out +++ b/test/langtools/tools/javac/6734819/T6734819c.out @@ -1,7 +1,9 @@ [attribute Y] [flow Y] +[warn Y] [attribute W] [flow W] +[warn W] [attribute Z] [flow Z] T6734819c.java:15:11: compiler.err.unreachable.stmt diff --git a/test/langtools/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out b/test/langtools/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out index 11cc81304f0..e240208da72 100644 --- a/test/langtools/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out +++ b/test/langtools/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out @@ -1,4 +1,5 @@ [attribute Explicit] [flow Explicit] +[warn Explicit] [desugar Explicit] [generate code Explicit] diff --git a/test/langtools/tools/javac/policy/test1/byfile.ABD.out b/test/langtools/tools/javac/policy/test1/byfile.ABD.out index dfa86a44132..0710de49c86 100644 --- a/test/langtools/tools/javac/policy/test1/byfile.ABD.out +++ b/test/langtools/tools/javac/policy/test1/byfile.ABD.out @@ -4,6 +4,9 @@ [flow A] [flow A1] [flow A2] +[warn A] +[warn A1] +[warn A2] [desugar A] [desugar A1] [desugar A2] diff --git a/test/langtools/tools/javac/policy/test1/byfile.ACD.out b/test/langtools/tools/javac/policy/test1/byfile.ACD.out index 66534ce00c5..70cc4856557 100644 --- a/test/langtools/tools/javac/policy/test1/byfile.ACD.out +++ b/test/langtools/tools/javac/policy/test1/byfile.ACD.out @@ -4,6 +4,9 @@ [flow A] [flow A1] [flow A2] +[warn A] +[warn A1] +[warn A2] [desugar A] [desugar A1] [desugar A2] diff --git a/test/langtools/tools/javac/policy/test1/bytodo.ABD.out b/test/langtools/tools/javac/policy/test1/bytodo.ABD.out index 5b3b8faace7..3296547f0ff 100644 --- a/test/langtools/tools/javac/policy/test1/bytodo.ABD.out +++ b/test/langtools/tools/javac/policy/test1/bytodo.ABD.out @@ -1,17 +1,21 @@ [attribute A] [flow A] +[warn A] [desugar A] [generate code A] [attribute A1] [flow A1] +[warn A1] [desugar A1] [generate code A1] [attribute A2] [flow A2] +[warn A2] [desugar A2] [generate code A2] [attribute B] [flow B] +[warn B] [desugar B] [generate code B] [attribute B1] diff --git a/test/langtools/tools/javac/policy/test1/bytodo.ACD.out b/test/langtools/tools/javac/policy/test1/bytodo.ACD.out index a29c0880de9..767a9912a05 100644 --- a/test/langtools/tools/javac/policy/test1/bytodo.ACD.out +++ b/test/langtools/tools/javac/policy/test1/bytodo.ACD.out @@ -1,17 +1,21 @@ [attribute A] [flow A] +[warn A] [desugar A] [generate code A] [attribute A1] [flow A1] +[warn A1] [desugar A1] [generate code A1] [attribute A2] [flow A2] +[warn A2] [desugar A2] [generate code A2] [attribute C] [flow C] +[warn C] [desugar C] [generate code C] [attribute C1] diff --git a/test/langtools/tools/javac/policy/test2/byfile.AB.out b/test/langtools/tools/javac/policy/test2/byfile.AB.out index 6d152c873aa..63a51108f36 100644 --- a/test/langtools/tools/javac/policy/test2/byfile.AB.out +++ b/test/langtools/tools/javac/policy/test2/byfile.AB.out @@ -1,7 +1,9 @@ [attribute A] [flow A] +[warn A] [attribute B] [flow B] +[warn B] [desugar B] [desugar A] [generate code A.A1] diff --git a/test/langtools/tools/javac/policy/test2/byfile.BA.out b/test/langtools/tools/javac/policy/test2/byfile.BA.out index 565ad138615..3c3567043a0 100644 --- a/test/langtools/tools/javac/policy/test2/byfile.BA.out +++ b/test/langtools/tools/javac/policy/test2/byfile.BA.out @@ -1,10 +1,12 @@ [attribute B] [flow B] +[warn B] [desugar B] [generate code B.Inner] [generate code B] [attribute A] [flow A] +[warn A] [desugar A] [generate code A.A1] [generate code A.A2] diff --git a/test/langtools/tools/javac/policy/test2/bytodo.AB.out b/test/langtools/tools/javac/policy/test2/bytodo.AB.out index 6d152c873aa..63a51108f36 100644 --- a/test/langtools/tools/javac/policy/test2/bytodo.AB.out +++ b/test/langtools/tools/javac/policy/test2/bytodo.AB.out @@ -1,7 +1,9 @@ [attribute A] [flow A] +[warn A] [attribute B] [flow B] +[warn B] [desugar B] [desugar A] [generate code A.A1] diff --git a/test/langtools/tools/javac/policy/test2/bytodo.BA.out b/test/langtools/tools/javac/policy/test2/bytodo.BA.out index 565ad138615..3c3567043a0 100644 --- a/test/langtools/tools/javac/policy/test2/bytodo.BA.out +++ b/test/langtools/tools/javac/policy/test2/bytodo.BA.out @@ -1,10 +1,12 @@ [attribute B] [flow B] +[warn B] [desugar B] [generate code B.Inner] [generate code B] [attribute A] [flow A] +[warn A] [desugar A] [generate code A.A1] [generate code A.A2] diff --git a/test/langtools/tools/javac/recovery/AttrRecovery.java b/test/langtools/tools/javac/recovery/AttrRecovery.java index db679915e08..c5d393a23b3 100644 --- a/test/langtools/tools/javac/recovery/AttrRecovery.java +++ b/test/langtools/tools/javac/recovery/AttrRecovery.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -115,7 +115,7 @@ public void overridable(C c) {} Path curPath = Path.of("."); List actual = new JavacTask(tb) .options("-XDrawDiagnostics", "-XDdev", - "-XDshould-stop.at=FLOW", "-Xlint:this-escape") + "-XDshould-stop.at=WARN", "-Xlint:this-escape") .sources(code) .outdir(curPath) .run(Expect.FAIL) diff --git a/test/micro/org/openjdk/bench/jdk/classfile/AbstractCorpusBenchmark.java b/test/micro/org/openjdk/bench/jdk/classfile/AbstractCorpusBenchmark.java index f3c934d9c65..ea361b4975b 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/AbstractCorpusBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/AbstractCorpusBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -44,8 +44,6 @@ @Warmup(iterations = 2) @Measurement(iterations = 4) @Fork(value = 1, jvmArgs = { - "--add-exports", "java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED", - "--add-exports", "java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.classfile.components=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.classfile.impl=ALL-UNNAMED"}) @State(Scope.Benchmark) diff --git a/test/micro/org/openjdk/bench/jdk/classfile/AdaptNull.java b/test/micro/org/openjdk/bench/jdk/classfile/AdaptNull.java index 55c33b36805..680d1626b2c 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/AdaptNull.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/AdaptNull.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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,10 +35,6 @@ public class AdaptNull extends AbstractCorpusBenchmark { @Param({ // "ARRAYCOPY", - "ASM_1", - "ASM_3", - "ASM_UNSHARED_3", -// "ASM_TREE", "SHARED_1", "SHARED_2", "SHARED_3", diff --git a/test/micro/org/openjdk/bench/jdk/classfile/ReadDeep.java b/test/micro/org/openjdk/bench/jdk/classfile/ReadDeep.java index 4165785135c..a134e04bd5a 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/ReadDeep.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/ReadDeep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,12 +29,6 @@ import java.lang.classfile.CompoundElement; import java.lang.classfile.MethodModel; import java.lang.classfile.instruction.LoadInstruction; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.tree.ClassNode; -import jdk.internal.org.objectweb.asm.tree.MethodNode; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Mode; @@ -45,55 +39,6 @@ */ public class ReadDeep extends AbstractCorpusBenchmark { - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmStreamCountLoads(Blackhole bh) { - for (byte[] bytes : classes) { - ClassReader cr = new ClassReader(bytes); - - var mv = new MethodVisitor(Opcodes.ASM9) { - int count = 0; - - @Override - public void visitVarInsn(int opcode, int var) { - ++count; - } - }; - - var visitor = new ClassVisitor(Opcodes.ASM9) { - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - return mv; - } - }; - cr.accept(visitor, 0); - bh.consume(mv.count); - } - } - - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmTreeCountLoads(Blackhole bh) { - for (byte[] bytes : classes) { - var mv = new MethodVisitor(Opcodes.ASM9) { - int count = 0; - - @Override - public void visitVarInsn(int opcode, int var) { - ++count; - } - }; - - ClassNode node = new ClassNode(); - ClassReader cr = new ClassReader(bytes); - cr.accept(node, 0); - for (MethodNode mn : node.methods) { - mn.accept(mv); - } - bh.consume(mv.count); - } - } - @Benchmark @BenchmarkMode(Mode.Throughput) public void jdkElementsCountLoads(Blackhole bh) { diff --git a/test/micro/org/openjdk/bench/jdk/classfile/ReadMetadata.java b/test/micro/org/openjdk/bench/jdk/classfile/ReadMetadata.java index 08b1b6312b1..0a12c5214e7 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/ReadMetadata.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/ReadMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -27,42 +27,11 @@ import java.lang.classfile.ClassModel; import java.lang.classfile.ClassFile; import java.lang.classfile.FieldModel; -import jdk.internal.org.objectweb.asm.*; -import jdk.internal.org.objectweb.asm.tree.*; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; public class ReadMetadata extends AbstractCorpusBenchmark { - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmStreamReadName(Blackhole bh) { - for (byte[] bytes : classes) { - ClassReader cr = new ClassReader(bytes); - var visitor = new ClassVisitor(Opcodes.ASM9) { - String theName; - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - theName = name; - } - }; - cr.accept(visitor, 0); - bh.consume(visitor.theName); - } - } - - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmTreeReadName(Blackhole bh) { - for (byte[] bytes : classes) { - ClassNode node = new ClassNode(); - ClassReader cr = new ClassReader(bytes); - cr.accept(node, 0); - bh.consume(node.name); - } - } - @Benchmark @BenchmarkMode(Mode.Throughput) public void jdkReadName(Blackhole bh) { @@ -90,43 +59,6 @@ public void jdkReadMemberNames(Blackhole bh) { } } - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmStreamCountFields(Blackhole bh) { - for (byte[] bytes : classes) { - ClassReader cr = new ClassReader(bytes); - var visitor = new ClassVisitor(Opcodes.ASM9) { - int count; - - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - if ((access & Opcodes.ACC_PUBLIC) != 1) { - ++count; - } - return null; - } - }; - cr.accept(visitor, 0); - bh.consume(visitor.count); - } - } - - @Benchmark - @BenchmarkMode(Mode.Throughput) - public void asmTreeCountFields(Blackhole bh) { - for (byte[] bytes : classes) { - int count = 0; - ClassNode node = new ClassNode(); - ClassReader cr = new ClassReader(bytes); - cr.accept(node, 0); - for (FieldNode fn : node.fields) - if ((fn.access & Opcodes.ACC_PUBLIC) != 1) { - ++count; - } - bh.consume(count); - } - } - @Benchmark @BenchmarkMode(Mode.Throughput) public void jdkTreeCountFields(Blackhole bh) { diff --git a/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java b/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java index 8af03a8b874..19c87442039 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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,27 +41,12 @@ import java.lang.classfile.MethodModel; import java.lang.classfile.MethodTransform; import jdk.internal.classfile.components.ClassRemapper; -import jdk.internal.org.objectweb.asm.AnnotationVisitor; -import jdk.internal.org.objectweb.asm.Attribute; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.FieldVisitor; -import jdk.internal.org.objectweb.asm.Handle; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.ModuleVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.RecordComponentVisitor; -import jdk.internal.org.objectweb.asm.TypePath; -import jdk.internal.org.objectweb.asm.tree.ClassNode; /** * Transforms */ public class Transforms { - static int ASM9 = 9 << 16 | 0 << 8; - public static final ClassTransform threeLevelNoop = (cb, ce) -> { if (ce instanceof MethodModel mm) { cb.transformMethod(mm, (mb, me) -> { @@ -123,38 +108,6 @@ public enum NoOpTransform { UNSHARED_3(false, threeLevelNoop), SHARED_3_NO_STACKMAP(true, threeLevelNoop, ClassFile.StackMapsOption.DROP_STACK_MAPS), SHARED_3_NO_DEBUG(true, threeLevelNoop, ClassFile.DebugElementsOption.DROP_DEBUG, ClassFile.LineNumbersOption.DROP_LINE_NUMBERS), - ASM_1(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - return cw.toByteArray(); - }), - ASM_UNSHARED_1(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - return cw.toByteArray(); - }), - ASM_3(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new CustomClassVisitor(cw), 0); - return cw.toByteArray(); - }), - ASM_UNSHARED_3(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new CustomClassVisitor(cw), 0); - return cw.toByteArray(); - }), - ASM_TREE(bytes -> { - ClassNode node = new ClassNode(); - ClassReader cr = new ClassReader(bytes); - cr.accept(node, 0); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - node.accept(cw); - return cw.toByteArray(); - }), CLASS_REMAPPER(bytes -> ClassRemapper.of(Map.of()).remapClass(ClassFile.of(), ClassFile.of().parse(bytes))); @@ -186,12 +139,6 @@ public enum NoOpTransform { } public enum InjectNopTransform { - ASM_NOP_SHARED(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(new NopClassVisitor(cw), 0); - return cw.toByteArray(); - }), NOP_SHARED(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -226,13 +173,6 @@ public void accept(CodeElement e) { } public enum SimpleTransform { - ASM_ADD_FIELD(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - cr.accept(cw, 0); - cw.visitField(0, "argleBargleWoogaWooga", "I", null, null); - return cw.toByteArray(); - }), HIGH_SHARED_ADD_FIELD(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -257,20 +197,6 @@ public void atEnd(ClassBuilder builder) { cb.withField("argleBargleWoogaWooga", ConstantDescs.CD_int, b -> { }); }); }), - ASM_DEL_METHOD(bytes -> { - ClassReader cr = new ClassReader(bytes); - jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(cr, jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES); - ClassVisitor v = new ClassVisitor(ASM9, cw) { - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - return (name.equals("hashCode") && descriptor.equals("()Z")) - ? null - : super.visitMethod(access, name, descriptor, signature, exceptions); - } - }; - cr.accept(cw, 0); - return cw.toByteArray(); - }), HIGH_SHARED_DEL_METHOD(bytes -> { var cc = ClassFile.of(); ClassModel cm = cc.parse(bytes); @@ -303,277 +229,4 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str } } - static class CustomClassVisitor extends ClassVisitor { - - public CustomClassVisitor(ClassVisitor writer) { - super(ASM9, writer); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public void visitSource(String source, String debug) { - super.visitSource(source, debug); - } - - @Override - public ModuleVisitor visitModule(String name, int access, String version) { - return super.visitModule(name, access, version); - } - - @Override - public void visitNestHost(String nestHost) { - super.visitNestHost(nestHost); - } - - @Override - public void visitOuterClass(String owner, String name, String descriptor) { - super.visitOuterClass(owner, name, descriptor); - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - return super.visitAnnotation(descriptor, visible); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitAttribute(Attribute attribute) { - super.visitAttribute(attribute); - } - - @Override - public void visitNestMember(String nestMember) { - super.visitNestMember(nestMember); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { - return super.visitRecordComponent(name, descriptor, signature); - } - - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - return super.visitField(access, name, descriptor, signature, value); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - return new CustomMethodVisitor(mv); - } - - @Override - public void visitEnd() { - super.visitEnd(); - } - }; - - - static class CustomMethodVisitor extends MethodVisitor { - - public CustomMethodVisitor(MethodVisitor methodVisitor) { - super(ASM9, methodVisitor); - } - - @Override - public void visitParameter(String name, int access) { - super.visitParameter(name, access); - } - - @Override - public AnnotationVisitor visitAnnotationDefault() { - return super.visitAnnotationDefault(); - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - return super.visitAnnotation(descriptor, visible); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitAnnotableParameterCount(int parameterCount, boolean visible) { - super.visitAnnotableParameterCount(parameterCount, visible); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) { - return super.visitParameterAnnotation(parameter, descriptor, visible); - } - - @Override - public void visitAttribute(Attribute attribute) { - super.visitAttribute(attribute); - } - - @Override - public void visitCode() { - super.visitCode(); - } - - @Override - public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { - super.visitFrame(type, numLocal, local, numStack, stack); - } - - @Override - public void visitInsn(int opcode) { - super.visitInsn(opcode); - } - - @Override - public void visitIntInsn(int opcode, int operand) { - super.visitIntInsn(opcode, operand); - } - - @Override - public void visitVarInsn(int opcode, int var) { - super.visitVarInsn(opcode, var); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - super.visitTypeInsn(opcode, type); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { - super.visitFieldInsn(opcode, owner, name, descriptor); - } - - @Override - @SuppressWarnings("deprecation") - public void visitMethodInsn(int opcode, String owner, String name, String descriptor) { - super.visitMethodInsn(opcode, owner, name, descriptor); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { - super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); - } - - @Override - public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { - super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - super.visitJumpInsn(opcode, label); - } - - @Override - public void visitLabel(Label label) { - super.visitLabel(label); - } - - @Override - public void visitLdcInsn(Object value) { - super.visitLdcInsn(value); - } - - @Override - public void visitIincInsn(int var, int increment) { - super.visitIincInsn(var, increment); - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { - super.visitTableSwitchInsn(min, max, dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - super.visitLookupSwitchInsn(dflt, keys, labels); - } - - @Override - public void visitMultiANewArrayInsn(String descriptor, int numDimensions) { - super.visitMultiANewArrayInsn(descriptor, numDimensions); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - super.visitTryCatchBlock(start, end, handler, type); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { - super.visitLocalVariable(name, descriptor, signature, start, end, index); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) { - return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); - } - - @Override - public void visitLineNumber(int line, Label start) { - super.visitLineNumber(line, start); - } - - @Override - public void visitMaxs(int maxStack, int maxLocals) { - super.visitMaxs(maxStack, maxLocals); - } - - @Override - public void visitEnd() { - super.visitEnd(); - } - }; - - static class NopClassVisitor extends CustomClassVisitor { - - public NopClassVisitor(ClassVisitor writer) { - super(writer); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - return new NopMethodVisitor(mv); - } - } - - static class NopMethodVisitor extends CustomMethodVisitor { - - public NopMethodVisitor(MethodVisitor methodVisitor) { - super(methodVisitor); - } - - @Override - public void visitCode() { - super.visitCode(); - visitInsn(Opcodes.NOP); - } - } - } diff --git a/test/micro/org/openjdk/bench/jdk/classfile/Write.java b/test/micro/org/openjdk/bench/jdk/classfile/Write.java index ffd5b8f1c5e..9317ef78806 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/Write.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -25,7 +25,6 @@ import java.lang.reflect.AccessFlag; import java.lang.classfile.ClassFile; import java.lang.classfile.attribute.SourceFileAttribute; -import jdk.internal.org.objectweb.asm.*; import org.openjdk.jmh.annotations.*; import java.io.FileOutputStream; import static java.lang.classfile.ClassFile.ACC_PUBLIC; @@ -57,8 +56,6 @@ @Warmup(iterations = 3) @Measurement(iterations = 5) @Fork(value = 1, jvmArgs = { - "--add-exports", "java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED", - "--add-exports", "java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.classfile.impl=ALL-UNNAMED"}) public class Write { static final int REPEATS = 40; @@ -70,76 +67,9 @@ public class Write { } METHOD_NAMES = names; } - static String checkFileAsm = "/tmp/asw/MyClass.class"; static String checkFileBc = "/tmp/byw/MyClass.class"; - static boolean writeClassAsm = Files.exists(Paths.get(checkFileAsm).getParent()); static boolean writeClassBc = Files.exists(Paths.get(checkFileBc).getParent()); - - @Benchmark - @BenchmarkMode(Mode.Throughput) - public byte[] asmStream() { - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - cw.visit(Opcodes.V12, Opcodes.ACC_PUBLIC, "MyClass", null, "java/lang/Object", null); - cw.visitSource("MyClass.java", null); - - { - MethodVisitor mv = cw.visitMethod(0, INIT_NAME, "()V", null, null); - mv.visitCode(); - Label startLabel = new Label(); - Label endLabel = new Label(); - mv.visitLabel(startLabel); - mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", INIT_NAME, "()V", false); - mv.visitInsn(Opcodes.RETURN); - mv.visitLabel(endLabel); - mv.visitLocalVariable("this", "LMyClass;", null, startLabel, endLabel, 1); - mv.visitMaxs(-1, -1); - mv.visitEnd(); - } - - for (int xi = 0; xi < REPEATS; ++xi) { - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_STATIC, METHOD_NAMES[xi], "([Ljava/lang/String;)V", null, null); - mv.visitCode(); - Label loopTop = new Label(); - Label loopEnd = new Label(); - Label startLabel = new Label(); - Label endLabel = new Label(); - Label iStart = new Label(); - mv.visitLabel(startLabel); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ISTORE, 1); - mv.visitLabel(iStart); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ISTORE, 2); - mv.visitLabel(loopTop); - mv.visitVarInsn(Opcodes.ILOAD, 2); - mv.visitIntInsn(Opcodes.BIPUSH, 10); - mv.visitJumpInsn(Opcodes.IF_ICMPGE, loopEnd); - mv.visitVarInsn(Opcodes.ILOAD, 1); - mv.visitVarInsn(Opcodes.ILOAD, 2); - mv.visitInsn(Opcodes.IMUL); - mv.visitVarInsn(Opcodes.ISTORE, 1); - mv.visitIincInsn(2, 1); - mv.visitJumpInsn(Opcodes.GOTO, loopTop); - mv.visitLabel(loopEnd); - mv.visitFieldInsn(Opcodes.GETSTATIC,"java/lang/System", "out", "Ljava/io/PrintStream;"); - mv.visitVarInsn(Opcodes.ILOAD, 1); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false); - mv.visitLabel(endLabel); - mv.visitInsn(Opcodes.RETURN); - mv.visitLocalVariable("fac", "I", null, startLabel, endLabel, 1); - mv.visitLocalVariable("i", "I", null, iStart, loopEnd, 2); - mv.visitMaxs(-1, -1); - mv.visitEnd(); - } - cw.visitEnd(); - - byte[] bytes = cw.toByteArray(); - if (writeClassAsm) writeClass(bytes, checkFileAsm); - return bytes; - } - @Benchmark @BenchmarkMode(Mode.Throughput) public byte[] jdkTree() { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java index 9f717908569..447eab012de 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -31,7 +31,7 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(1) +@Fork(value=1, jvmArgs={"--add-modules=jdk.incubator.vector"}) public class SpiltReplicate { @CompilerControl(CompilerControl.Mode.DONT_INLINE) public long broadcastInt() { diff --git a/test/micro/org/openjdk/bench/vm/compiler/MergeLoadBench.java b/test/micro/org/openjdk/bench/vm/compiler/MergeLoadBench.java new file mode 100644 index 00000000000..e29b5373791 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/MergeLoadBench.java @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import jdk.internal.misc.Unsafe; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Fork(value = 1, jvmArgs = {"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"}) +public class MergeLoadBench { + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + final static VarHandle + INT_L = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.LITTLE_ENDIAN), + INT_B = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.BIG_ENDIAN), + LONG_L = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN), + LONG_B = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN), + CHAR_L = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.LITTLE_ENDIAN), + CHAR_B = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.BIG_ENDIAN); + + final static int NUMBERS = 8192; + + final byte[] bytes4 = new byte[NUMBERS * 4]; + final byte[] bytes8 = new byte[NUMBERS * 8]; + final int [] ints = new int [NUMBERS ]; + final long[] longs = new long[NUMBERS ]; + + @Setup + public void setup() { + Random r = new Random(); + for (int i = 0; i < ints.length; i++) { + ints[i] = r.nextInt(); + INT_L.set(bytes4, i * 4, i); + } + + for (int i = 0; i < longs.length; i++) { + longs[i] = r.nextLong(); + LONG_L.set(bytes8, i * 8, i); + } + } + + /* + * The names of these cases have the following `B/L/V/U` suffixes, which are: + * ``` + * B BigEndian + * L LittleEndian + * V VarHandle + * U Unsafe + * R ReverseBytes + * C Unsafe.getChar & putChar + * S Unsafe.getShort & putShort + * ``` + */ + + @Benchmark + public void getIntB(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntB(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntBU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntBU(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntBV(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += (int) INT_B.get(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntL(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntL(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntLU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntLU(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntLV(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += (int) INT_L.get(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntRB(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntRB(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntRBU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntRBU(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntRL(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntRL(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntRLU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += getIntRLU(bytes4, i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getIntRU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += Integer.reverseBytes( + UNSAFE.getInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4)); + } + BH.consume(sum); + } + + @Benchmark + public void getIntU(Blackhole BH) { + int sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += UNSAFE.getInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4); + } + BH.consume(sum); + } + + @Benchmark + public void getLongB(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongB(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongBU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongBU(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongBV(Blackhole BH) { + long sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += (long) LONG_B.get(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongL(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongL(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongLU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongLU(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongLV(Blackhole BH) { + long sum = 0; + for (int i = 0; i < ints.length; i++) { + sum += (long) LONG_L.get(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongRB(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongRB(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongRBU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongRBU(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongRL(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongRL(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongRLU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += getLongRLU(bytes8, i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getLongRU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += Long.reverseBytes( + UNSAFE.getLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8)); + } + BH.consume(sum); + } + + @Benchmark + public void getLongU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + sum += UNSAFE.getLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8); + } + BH.consume(sum); + } + + @Benchmark + public void getCharB(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = getCharB(bytes4, i); + sum += c; + } + BH.consume(sum); + } + + @Benchmark + public void getCharBV(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = (char) CHAR_B.get(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); + sum += c; + } + BH.consume(sum); + } + + @Benchmark + public void getCharBU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = getCharBU(bytes4, i); + sum += c; + } + BH.consume(sum); + } + + @Benchmark + public void getCharL(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = getCharL(bytes4, i); + sum += c; + } + BH.consume(sum); + } + @Benchmark + public void getCharLU(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = getCharLU(bytes4, i); + sum += c; + } + BH.consume(sum); + } + + + @Benchmark + public void getCharLV(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = (char) CHAR_L.get(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); + sum += c; + } + BH.consume(sum); + } + + @Benchmark + public void getCharC(Blackhole BH) { + long sum = 0; + for (int i = 0; i < longs.length; i++) { + char c = UNSAFE.getChar(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); + sum += c; + } + BH.consume(sum); + } + + static int getIntB(byte[] array, int offset) { + return ((array[offset ] & 0xff) << 24) + | ((array[offset + 1] & 0xff) << 16) + | ((array[offset + 2] & 0xff) << 8) + | ((array[offset + 3] & 0xff) ); + } + + static int getIntBU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; + return ((UNSAFE.getByte(array, address ) & 0xff) << 24) + | ((UNSAFE.getByte(array, address + 1) & 0xff) << 16) + | ((UNSAFE.getByte(array, address + 2) & 0xff) << 8) + | ((UNSAFE.getByte(array, address + 3) & 0xff) ); + } + + static int getIntL(byte[] array, int offset) { + return ((array[offset ] & 0xff) ) + | ((array[offset + 1] & 0xff) << 8) + | ((array[offset + 2] & 0xff) << 16) + | ((array[offset + 3] & 0xff) << 24); + } + + static int getIntRB(byte[] array, int offset) { + return Integer.reverseBytes(getIntB(array, offset)); + } + + static int getIntRBU(byte[] array, int offset) { + return Integer.reverseBytes(getIntBU(array, offset)); + } + + static int getIntRL(byte[] array, int offset) { + return Integer.reverseBytes(getIntL(array, offset)); + } + + static int getIntRLU(byte[] array, int offset) { + return Integer.reverseBytes(getIntLU(array, offset)); + } + + static long getLongB(byte[] array, int offset) { + return (((long) array[offset ] & 0xff) << 56) + | (((long) array[offset + 1] & 0xff) << 48) + | (((long) array[offset + 2] & 0xff) << 40) + | (((long) array[offset + 3] & 0xff) << 32) + | (((long) array[offset + 4] & 0xff) << 24) + | (((long) array[offset + 5] & 0xff) << 16) + | (((long) array[offset + 6] & 0xff) << 8) + | (((long) array[offset + 7] & 0xff) ); + } + + static long getLongBU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; + return (((long)(UNSAFE.getByte(array, address) & 0xff)) << 56) + | (((long)(UNSAFE.getByte(array, address + 1) & 0xff)) << 48) + | (((long)(UNSAFE.getByte(array, address + 2) & 0xff)) << 40) + | (((long)(UNSAFE.getByte(array, address + 3) & 0xff)) << 32) + | (((long)(UNSAFE.getByte(array, address + 4) & 0xff)) << 24) + | (((long)(UNSAFE.getByte(array, address + 5) & 0xff)) << 16) + | (((long)(UNSAFE.getByte(array, address + 6) & 0xff)) << 8) + | (((long)(UNSAFE.getByte(array, address + 7) & 0xff)) ); + } + + public static long getLongL(byte[] array, int offset) { + return (((long) array[offset ] & 0xff) ) + | (((long) array[offset + 1] & 0xff) << 8) + | (((long) array[offset + 2] & 0xff) << 16) + | (((long) array[offset + 3] & 0xff) << 24) + | (((long) array[offset + 4] & 0xff) << 32) + | (((long) array[offset + 5] & 0xff) << 40) + | (((long) array[offset + 6] & 0xff) << 48) + | (((long) array[offset + 7] & 0xff) << 56); + } + + static long getLongLU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; + return (((long)(UNSAFE.getByte(array, address ) & 0xff)) ) + | (((long)(UNSAFE.getByte(array, address + 1) & 0xff)) << 8) + | (((long)(UNSAFE.getByte(array, address + 2) & 0xff)) << 16) + | (((long)(UNSAFE.getByte(array, address + 3) & 0xff)) << 24) + | (((long)(UNSAFE.getByte(array, address + 4) & 0xff)) << 32) + | (((long)(UNSAFE.getByte(array, address + 5) & 0xff)) << 40) + | (((long)(UNSAFE.getByte(array, address + 6) & 0xff)) << 48) + | (((long)(UNSAFE.getByte(array, address + 7) & 0xff)) << 56); + } + + static long getLongRB(byte[] array, int offset) { + return getLongB(array, offset); + } + + static long getLongRBU(byte[] array, int offset) { + return getLongBU(array, offset); + } + + static long getLongRL(byte[] array, int offset) { + return getLongL(array, offset); + } + + static long getLongRLU(byte[] array, int offset) { + return getLongLU(array, offset); + } + + public static int getIntLU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; + return ((UNSAFE.getByte(array, address ) & 0xff) ) + | ((UNSAFE.getByte(array, address + 1) & 0xff) << 8) + | ((UNSAFE.getByte(array, address + 2) & 0xff) << 16) + | ((UNSAFE.getByte(array, address + 3) & 0xff) << 24); + } + + public static char getCharB(byte[] val, int index) { + index <<= 1; + return (char)(((val[index ] & 0xff) << 8) + | ((val[index + 1] & 0xff))); + } + + public static char getCharBR(byte[] val, int index) { + return Character.reverseBytes(getCharB(val, index)); + } + + public static char getCharL(byte[] val, int index) { + index <<= 1; + return (char)(((val[index ] & 0xff)) + | ((val[index + 1] & 0xff) << 8)); + } + + public static char getCharLR(byte[] val, int index) { + return Character.reverseBytes(getCharL(val, index)); + } + + public static char getCharBU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); + return (char) (((UNSAFE.getByte(array, address ) & 0xff) << 8) + | ((UNSAFE.getByte(array, address + 1) & 0xff) )); + } + + public static char getCharLU(byte[] array, int offset) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); + return (char) (((UNSAFE.getByte(array, address ) & 0xff) ) + | ((UNSAFE.getByte(array, address + 1) & 0xff) << 8)); + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/MergeStoreBench.java b/test/micro/org/openjdk/bench/vm/compiler/MergeStoreBench.java index 870422de256..88b68868813 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/MergeStoreBench.java +++ b/test/micro/org/openjdk/bench/vm/compiler/MergeStoreBench.java @@ -25,13 +25,9 @@ import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.lang.reflect.Field; import java.nio.ByteOrder; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -41,18 +37,19 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) -@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgs = {"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"}) +@Fork(value = 1, jvmArgs = {"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MergeStoreBench { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - final static VarHandle INT_L = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.LITTLE_ENDIAN); - final static VarHandle INT_B = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.BIG_ENDIAN); - final static VarHandle LONG_L = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN); - final static VarHandle LONG_B = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN); - final static VarHandle CHAR_L = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.LITTLE_ENDIAN); - final static VarHandle CHAR_B = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.BIG_ENDIAN); + final static VarHandle + INT_L = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.LITTLE_ENDIAN), + INT_B = MethodHandles.byteArrayViewVarHandle(int[].class , ByteOrder.BIG_ENDIAN), + LONG_L = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN), + LONG_B = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN), + CHAR_L = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.LITTLE_ENDIAN), + CHAR_B = MethodHandles.byteArrayViewVarHandle(char[].class, ByteOrder.BIG_ENDIAN); final static int NUMBERS = 8192; @@ -89,115 +86,6 @@ public void setup() { * ``` */ - @Benchmark - public void getIntB(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntB(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntBU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntBU(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntBV(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += (int) INT_B.get(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntL(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntL(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntLU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntLU(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntLV(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += (int) INT_L.get(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntRB(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntRB(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntRBU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntRBU(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntRL(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntRL(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntRLU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += getIntRLU(bytes4, i * 4); - } - BH.consume(sum); - } - - @Benchmark - public void getIntRU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += Integer.reverseBytes( - UNSAFE.getInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4)); - } - BH.consume(sum); - } - - @Benchmark - public void getIntU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += UNSAFE.getInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4); - } - BH.consume(sum); - } - @Benchmark public void setIntB(Blackhole BH) { int sum = 0; @@ -211,613 +99,396 @@ public void setIntB(Blackhole BH) { @Benchmark public void setIntBU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntBU(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntBU(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntBV(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - INT_B.set(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + INT_B.set(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntL(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntL(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntL(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntLU(Blackhole BH) { - int sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntLU(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntLU(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntLV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - INT_L.set(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + INT_L.set(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntRB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntRB(bytes4, i * 4, ints[i]); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntRB(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntRBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntRBU(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntRBU(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntRL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntRL(bytes4, i * 4, ints[i]); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntRL(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntRLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - setIntRLU(bytes4, i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + setIntRLU(bytes4, off, ints[i]); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntRU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - v = Integer.reverseBytes(v); - UNSAFE.putInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4, v); - sum += v; + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + UNSAFE.putInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, Integer.reverseBytes(ints[i])); + off += 4; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setIntU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - int v = ints[i]; - UNSAFE.putInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 4, v); - sum += v; - } - BH.consume(sum); - } - - @Benchmark - public void getLongB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongB(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongBU(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongBV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += (long) LONG_B.get(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongL(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongLU(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongLV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += (long) LONG_L.get(bytes8, i * 8); + int off = 0; + for (int i = ints.length - 1; i >= 0; i--) { + UNSAFE.putInt(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, ints[i]); + off += 4; } - BH.consume(sum); - } - - @Benchmark - public void getLongRB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongRB(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongRBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongRBU(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongRL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongRL(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongRLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += getLongRLU(bytes8, i * 8); - } - BH.consume(sum); - } - - @Benchmark - public void getLongRU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += Long.reverseBytes( - UNSAFE.getLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8)); - } - BH.consume(sum); - } - - @Benchmark - public void getLongU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - sum += UNSAFE.getLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8); - } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongB(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongB(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongBU(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongBU(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongBV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - LONG_B.set(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + LONG_B.set(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongL(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongL(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongLU(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongLU(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongLV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - LONG_L.set(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + LONG_L.set(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongRB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongRB(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongRB(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongRBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongRBU(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongRBU(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongRL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongRL(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongRL(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongRLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - setLongRLU(bytes8, i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + setLongRLU(bytes8, off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongRU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - v = Long.reverseBytes(v); - UNSAFE.putLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8, v); - sum += v; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + UNSAFE.putLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, Long.reverseBytes(longs[i])); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark public void setLongU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - long v = longs[i]; - UNSAFE.putLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 8, v); - sum += v; - } - BH.consume(sum); - } - - @Benchmark - public void getCharB(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = getCharB(bytes4, i); - sum += c; + int off = 0; + for (int i = longs.length - 1; i >= 0; i--) { + UNSAFE.putLong(bytes8, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, longs[i]); + off += 8; } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void getCharBV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = (char) CHAR_B.get(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); - sum += c; - } - BH.consume(sum); - } - - @Benchmark - public void getCharBU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = getCharBU(bytes4, i); - sum += c; + public void setCharBS(Blackhole BH) { + int off = 0; + for (int i = chars.length - 1; i >= 0; i--) { + putShortB(bytes4, off, chars[i]); + off += 2; } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void getCharL(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = getCharL(bytes4, i); - sum += c; - } - BH.consume(sum); - } - @Benchmark - public void getCharLU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = getCharLU(bytes4, i); - sum += c; + public void setCharBV(Blackhole BH) { + int off = 0; + for (int i = chars.length - 1; i >= 0; i--) { + CHAR_B.set(bytes4, off, chars[i]); + off += 2; } - BH.consume(sum); + BH.consume(off); } - @Benchmark - public void getCharLV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = (char) CHAR_L.get(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); - sum += c; + public void setCharLS(Blackhole BH) { + int off = 0; + for (int i = chars.length - 1; i >= 0; i--) { + putShortL(bytes4, off, chars[i]); + off += 2; } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void getCharC(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - char c = UNSAFE.getChar(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2); - sum += c; + public void setCharLV(Blackhole BH) { + int off = 0; + for (int i = chars.length - 1; i >= 0; i--) { + CHAR_L.set(bytes4, off, chars[i]); + off += 2; } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void setCharBS(Blackhole BH) { - long sum = 0; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - putShortB(bytes4, i * 2, c); - sum += c; + public void setCharC(Blackhole BH) { + int off = 0; + for (int i = chars.length - 1; i >= 0; i--) { + UNSAFE.putChar(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + off, chars[i]); + off += 2; } - BH.consume(sum); + BH.consume(off); } + /* + * putChars4 and putBytes4 Test whether four constant chars can be MergeStored + * + */ @Benchmark - public void setCharBV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - CHAR_B.set(bytes4, i * 2, c); - sum += c; + public void putBytes4(Blackhole BH) { + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putBytes4(bytes4, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void setCharLS(Blackhole BH) { - long sum = 0; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - putShortL(bytes4, i * 2, c); - sum += c; + public void putBytes4X(Blackhole BH) { + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putBytes4X(bytes4, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void setCharLV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - CHAR_L.set(bytes4, i * 2, c); - sum += c; + public void putBytes4U(Blackhole BH) { + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putBytes4U(bytes4, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark - public void setCharC(Blackhole BH) { - long sum = 0; - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - UNSAFE.putChar(bytes4, Unsafe.ARRAY_BYTE_BASE_OFFSET + i * 2, c); - sum += c; + @SuppressWarnings("deprecation") + public void putBytes4GetBytes(Blackhole BH) { + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + "null".getBytes(0, 4, bytes4, off); + off += 4; } - BH.consume(sum); + BH.consume(off); } - /* - * putChars4 Test whether four constant chars can be MergeStored - * - */ @Benchmark public void putChars4B(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4B(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4B(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4BU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4BU(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4BU(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4BV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4BV(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4BV(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4L(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4L(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4L(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4LU(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4LU(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4LU(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4LV(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4LV(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4LV(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4C(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4C(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4C(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); + BH.consume(off); } @Benchmark public void putChars4S(Blackhole BH) { - long sum = 0; - for (int i = 0; i < longs.length; i++) { - putChars4S(bytes8, i * 4); - sum += longs[i]; + int off = 0; + for (int i = 0; i < NUMBERS; i++) { + off = putChars4S(bytes8, off, 'n', 'u', 'l', 'l'); } - BH.consume(sum); - } - - static int getIntB(byte[] array, int offset) { - return ((array[offset ] & 0xff) << 24) - | ((array[offset + 1] & 0xff) << 16) - | ((array[offset + 2] & 0xff) << 8) - | ((array[offset + 3] & 0xff) ); - } - - static int getIntBU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; - return ((UNSAFE.getByte(array, address ) & 0xff) << 24) - | ((UNSAFE.getByte(array, address + 1) & 0xff) << 16) - | ((UNSAFE.getByte(array, address + 2) & 0xff) << 8) - | ((UNSAFE.getByte(array, address + 3) & 0xff) ); - } - - static int getIntL(byte[] array, int offset) { - return ((array[offset ] & 0xff) ) - | ((array[offset + 1] & 0xff) << 8) - | ((array[offset + 2] & 0xff) << 16) - | ((array[offset + 3] & 0xff) << 24); - } - - static int getIntRB(byte[] array, int offset) { - return Integer.reverseBytes(getIntB(array, offset)); - } - - static int getIntRBU(byte[] array, int offset) { - return Integer.reverseBytes(getIntBU(array, offset)); - } - - static int getIntRL(byte[] array, int offset) { - return Integer.reverseBytes(getIntL(array, offset)); - } - - static int getIntRLU(byte[] array, int offset) { - return Integer.reverseBytes(getIntLU(array, offset)); + BH.consume(off); } static void setIntB(byte[] array, int offset, int value) { @@ -870,68 +541,6 @@ public static void setIntRBU(byte[] array, int offset, int value) { setIntBU(array, offset, value); } - static long getLongB(byte[] array, int offset) { - return (((long) array[offset ] & 0xff) << 56) - | (((long) array[offset + 1] & 0xff) << 48) - | (((long) array[offset + 2] & 0xff) << 40) - | (((long) array[offset + 3] & 0xff) << 32) - | (((long) array[offset + 4] & 0xff) << 24) - | (((long) array[offset + 5] & 0xff) << 16) - | (((long) array[offset + 6] & 0xff) << 8) - | (((long) array[offset + 7] & 0xff) ); - } - - static long getLongBU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; - return (((long)(UNSAFE.getByte(array, address) & 0xff)) << 56) - | (((long)(UNSAFE.getByte(array, address + 1) & 0xff)) << 48) - | (((long)(UNSAFE.getByte(array, address + 2) & 0xff)) << 40) - | (((long)(UNSAFE.getByte(array, address + 3) & 0xff)) << 32) - | (((long)(UNSAFE.getByte(array, address + 4) & 0xff)) << 24) - | (((long)(UNSAFE.getByte(array, address + 5) & 0xff)) << 16) - | (((long)(UNSAFE.getByte(array, address + 6) & 0xff)) << 8) - | (((long)(UNSAFE.getByte(array, address + 7) & 0xff)) ); - } - - public static long getLongL(byte[] array, int offset) { - return (((long) array[offset ] & 0xff) ) - | (((long) array[offset + 1] & 0xff) << 8) - | (((long) array[offset + 2] & 0xff) << 16) - | (((long) array[offset + 3] & 0xff) << 24) - | (((long) array[offset + 4] & 0xff) << 32) - | (((long) array[offset + 5] & 0xff) << 40) - | (((long) array[offset + 6] & 0xff) << 48) - | (((long) array[offset + 7] & 0xff) << 56); - } - - static long getLongLU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; - return (((long)(UNSAFE.getByte(array, address ) & 0xff)) ) - | (((long)(UNSAFE.getByte(array, address + 1) & 0xff)) << 8) - | (((long)(UNSAFE.getByte(array, address + 2) & 0xff)) << 16) - | (((long)(UNSAFE.getByte(array, address + 3) & 0xff)) << 24) - | (((long)(UNSAFE.getByte(array, address + 4) & 0xff)) << 32) - | (((long)(UNSAFE.getByte(array, address + 5) & 0xff)) << 40) - | (((long)(UNSAFE.getByte(array, address + 6) & 0xff)) << 48) - | (((long)(UNSAFE.getByte(array, address + 7) & 0xff)) << 56); - } - - static long getLongRB(byte[] array, int offset) { - return getLongB(array, offset); - } - - static long getLongRBU(byte[] array, int offset) { - return getLongBU(array, offset); - } - - static long getLongRL(byte[] array, int offset) { - return getLongL(array, offset); - } - - static long getLongRLU(byte[] array, int offset) { - return getLongLU(array, offset); - } - static void setLongB(byte[] array, int offset, long value) { array[offset] = (byte) (value >> 56); array[offset + 1] = (byte) (value >> 48); @@ -998,112 +607,95 @@ public static void setLongLU(byte[] array, int offset, long value) { UNSAFE.putByte(array, address + 7, (byte) (value >> 56)); } - public static int getIntLU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; - return ((UNSAFE.getByte(array, address ) & 0xff) ) - | ((UNSAFE.getByte(array, address + 1) & 0xff) << 8) - | ((UNSAFE.getByte(array, address + 2) & 0xff) << 16) - | ((UNSAFE.getByte(array, address + 3) & 0xff) << 24); - } - - public static char getCharB(byte[] val, int index) { - index <<= 1; - return (char)(((val[index ] & 0xff) << 8) - | ((val[index + 1] & 0xff))); - } - - public static char getCharBR(byte[] val, int index) { - return Character.reverseBytes(getCharB(val, index)); - } - - public static char getCharL(byte[] val, int index) { - index <<= 1; - return (char)(((val[index ] & 0xff)) - | ((val[index + 1] & 0xff) << 8)); + public int putBytes4(byte[] bytes, int offset, int c0, int c1, int c2, int c3) { + bytes[offset ] = (byte) c0; + bytes[offset + 1] = (byte) c1; + bytes[offset + 2] = (byte) c2; + bytes[offset + 3] = (byte) c3; + return offset + 4; } - public static char getCharLR(byte[] val, int index) { - return Character.reverseBytes(getCharL(val, index)); + public int putBytes4X(byte[] bytes, int offset, int c0, int c1, int c2, int c3) { + bytes[offset++] = (byte) c0; + bytes[offset++] = (byte) c1; + bytes[offset++] = (byte) c2; + bytes[offset++] = (byte) c3; + return offset; } - public static char getCharBU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); - return (char) (((UNSAFE.getByte(array, address ) & 0xff) << 8) - | ((UNSAFE.getByte(array, address + 1) & 0xff) )); - } - - public static char getCharLU(byte[] array, int offset) { - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); - return (char) (((UNSAFE.getByte(array, address ) & 0xff) ) - | ((UNSAFE.getByte(array, address + 1) & 0xff) << 8)); + public int putBytes4U(byte[] bytes, int offset, int c0, int c1, int c2, int c3) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; + UNSAFE.putByte(bytes, address , (byte) c0); + UNSAFE.putByte(bytes, address + 1, (byte) c1); + UNSAFE.putByte(bytes, address + 2, (byte) c2); + UNSAFE.putByte(bytes, address + 3, (byte) c3); + return offset + 4; } - public void putChars4B(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; + public int putChars4B(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { putShortB(bytes, offset , c0); putShortB(bytes, offset + 1, c1); putShortB(bytes, offset + 2, c2); putShortB(bytes, offset + 3, c3); + return offset + 4; } - public void putChars4BU(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; + public int putChars4BU(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { putShortBU(bytes, offset , c0); putShortBU(bytes, offset + 1, c1); putShortBU(bytes, offset + 2, c2); putShortBU(bytes, offset + 3, c3); + return offset + 4; } - public void putChars4BV(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; - offset <<= 1; - CHAR_B.set(bytes, offset , c0); + public int putChars4BV(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { + CHAR_B.set(bytes, offset , c0); CHAR_B.set(bytes, offset + 2, c1); CHAR_B.set(bytes, offset + 4, c2); CHAR_B.set(bytes, offset + 6, c3); + return offset + 8; } - public void putChars4L(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; + public int putChars4L(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { putShortL(bytes, offset , c0); putShortL(bytes, offset + 1, c1); putShortL(bytes, offset + 2, c2); putShortL(bytes, offset + 3, c3); + return offset + 4; } - public void putChars4LV(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; - offset <<= 1; + public int putChars4LV(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { CHAR_L.set(bytes, offset , c0); CHAR_L.set(bytes, offset + 2, c1); CHAR_L.set(bytes, offset + 4, c2); CHAR_L.set(bytes, offset + 6, c3); + return offset + 8; } - public void putChars4LU(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; + public int putChars4LU(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { putShortLU(bytes, offset , c0); putShortLU(bytes, offset + 1, c1); putShortLU(bytes, offset + 2, c2); putShortLU(bytes, offset + 3, c3); + return offset + 4; } - public void putChars4C(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); + public int putChars4C(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; UNSAFE.putChar(bytes, address , c0); UNSAFE.putChar(bytes, address + 2, c1); UNSAFE.putChar(bytes, address + 4, c2); UNSAFE.putChar(bytes, address + 6, c3); + return offset + 8; } - public void putChars4S(byte[] bytes, int offset) { - char c0 = 'n', c1 = 'u', c2 = 'l', c3 = 'l'; - final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + (offset << 1); + public int putChars4S(byte[] bytes, int offset, char c0, char c1, char c2, char c3) { + final long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; UNSAFE.putShort(bytes, address , (short) c0); UNSAFE.putShort(bytes, address + 2, (short) c1); UNSAFE.putShort(bytes, address + 4, (short) c2); UNSAFE.putShort(bytes, address + 6, (short) c3); + return offset + 8; } private static void putShortB(byte[] val, int index, int c) { @@ -1129,4 +721,9 @@ public static void putShortLU(byte[] array, int offset, int c) { UNSAFE.putByte(array, address , (byte) (c )); UNSAFE.putByte(array, address + 1, (byte) (c >> 8)); } + + @Fork(value = 1, jvmArgs = { + "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:+UnlockDiagnosticVMOptions", "-XX:-MergeStores" + }) + public static class MergeStoresDisabled extends MergeStoreBench {} }