Compare commits

...

75 Commits

Author SHA1 Message Date
Tobias Hartmann
2d4731917d 8348631: Crash in PredictedCallGenerator::generate after JDK-8347006
Reviewed-by: chagedorn
Backport-of: 55c3e78f4e
2025-01-29 07:33:41 +00:00
Chen Liang
612ae737c0 8342465: Improve API documentation for java.lang.classfile
Reviewed-by: asotona
Backport-of: 1d8ccb8920
2025-01-27 23:31:47 +00:00
Justin Lu
a315b9326b 8347498: JDK 24 RDP2 L10n resource files update
Reviewed-by: dnguyen, naoto, iris
Backport-of: dec93675ab
2025-01-27 17:24:45 +00:00
Mikael Vidstedt
ab43ba0ef8 8348327: Incorrect march flag when building libsleef/vector_math_neon.c
Reviewed-by: erikj, shade
Backport-of: 3ebf88996f
2025-01-24 18:07:26 +00:00
Chen Liang
564e0a2076 8342466: Improve API documentation for java.lang.classfile.attribute
8347762: ClassFile attribute specification refers to non-SE modules

Reviewed-by: asotona
Backport-of: 973c630777
2025-01-24 14:56:35 +00:00
Richard Reingruber
53aa9f2596 8347817: Timeouts running test/jdk/java/lang/String/concat/HiddenClassUnloading.java with fastdebug builds
Reviewed-by: mdoerr
Backport-of: 15d6469e8d
2025-01-23 08:28:58 +00:00
Calvin Cheung
99e21c6aaf 8348013: [doc] fix typo in java.md caused by JDK-8347763
Reviewed-by: iklam
Backport-of: e1cf3517ae
2025-01-22 18:47:06 +00:00
Jaikiran Pai
4ce95c95ef Merge
Reviewed-by: dfuchs
2025-01-22 11:28:52 +00:00
Christian Hagedorn
93ea8e708d 8330045: Enhance array handling
Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org>
Co-authored-by: Emanuel Peter <epeter@openjdk.org>
Co-authored-by: Francisco Ferrari Bihurriet <fferrari@redhat.com>
Co-authored-by: Martin Balao <mbalao@redhat.com>
Reviewed-by: rhalade, ahgross, thartmann, epeter, adinn, roland
2025-01-22 14:56:30 +05:30
Roger Riggs
a9fae67913 8339180: Enhanced Building of Processes: Follow-on Issue
Reviewed-by: naoto, djelinski
2025-01-22 14:56:30 +05:30
Jayathirth D V
aaf3415de8 8336564: Enhance mask blit functionality redux
Reviewed-by: rhalade, mschoene, psadhukhan, prr
2025-01-22 14:56:30 +05:30
Roger Riggs
535922059c 8335428: Enhanced Building of Processes
Reviewed-by: rhalade, djelinski
2025-01-22 14:56:30 +05:30
Calvin Cheung
bc19494216 8347763: [doc] Add documentation of module options for JEP 483
Reviewed-by: iklam
Backport-of: 17e3df652f
2025-01-22 05:52:55 +00:00
William Kemper
febcfd69ff 8345750: Shenandoah: Test TestJcmdHeapDump.java#aggressive intermittent assert(gc_cause() == GCCause::_no_gc) failed: Over-writing cause
Reviewed-by: ysr
Backport-of: 6a29a8110e
2025-01-21 23:10:22 +00:00
Markus Grönlund
1495f7addb 8345493: JFR: JVM.flush hangs intermittently
Reviewed-by: egahlin
Backport-of: 4257215a9f
2025-01-15 16:42:31 +00:00
Weijun Wang
c141aa1e08 8347596: Update HSS/LMS public key encoding
Reviewed-by: mullan
Backport-of: 0ee6ba9c4c
2025-01-15 14:26:23 +00:00
Coleen Phillimore
467f407037 8344068: Windows x86-64: Out of CodeBuffer space when generating final stubs
Reviewed-by: kvn, jwaters
Backport-of: 830173fcb0
2025-01-15 12:37:08 +00:00
Qizheng Xing
f7858e2422 8346831: Remove the extra closing parenthesis in CTW Makefile
Reviewed-by: thartmann, chagedorn
Backport-of: 79958470e0
2025-01-15 08:21:47 +00:00
Jan Lahoda
6965840e0d 8347646: module-info classfile missing the preview flag
Reviewed-by: asotona
Backport-of: bb93f67ea8
2025-01-15 05:14:53 +00:00
Erik Gahlin
1399f253b0 8343510: JFR: Remove AccessControlContext from FlightRecorder::addListener specification
Reviewed-by: mgronlun
Backport-of: 1bf2f5c8a9
2025-01-14 22:31:31 +00:00
Joe Darcy
f45a23cabd 8347605: Use spec tag to refer to IEEE 754 standard
Reviewed-by: liach, bpb, iris
Backport-of: 7c883c284d
2025-01-14 16:39:26 +00:00
Christian Hagedorn
f42e2c10c6 8347554: [BACKOUT] C2: implement optimization for series of Add of unique value
Reviewed-by: kvn, thartmann
Backport-of: 062f2dcfe5
2025-01-14 15:20:53 +00:00
Weijun Wang
57c46ac2fe 8342062: Reformat keytool and jarsigner output for keys with a named parameter set
Reviewed-by: mullan
Backport-of: fa5ff82eb3
2025-01-14 14:06:36 +00:00
Viktor Klang
24053d9b6a 8347274: Gatherers.mapConcurrent exhibits undesired behavior under variable delays, interruption, and finishing
Reviewed-by: alanb
Backport-of: 450636ae28
2025-01-14 13:31:29 +00:00
Damon Fenacci
e76cc44502 8347407: [BACKOUT] C1/C2 don't handle allocation failure properly during initialization (RuntimeStub::new_runtime_stub fatal crash)
Reviewed-by: thartmann, kvn
Backport-of: b37f123625
2025-01-14 07:35:21 +00:00
Chen Liang
4a623a2b6d 8342468: Improve API documentation for java.lang.classfile.constantpool
8347163: Javadoc error in ConstantPoolBuilder after JDK-8342468

Reviewed-by: asotona
Backport-of: bcefab5e55
2025-01-13 17:00:54 +00:00
Abhishek Kumar
ecdc322029 8339728: [Accessibility,Windows,JAWS] Bug in the getKeyChar method of the AccessBridge class
Reviewed-by: aivanov, kizune
Backport-of: a46ae7031e
2025-01-13 16:37:38 +00:00
Tobias Hartmann
da74fbd920 8347006: LoadRangeNode floats above array guard in arraycopy intrinsic
Reviewed-by: chagedorn
Backport-of: 82e2a79122
2025-01-13 13:45:19 +00:00
Patricio Chilano Mateo
f0a89c5d8e 8310340: assert(_thread->is_interp_only_mode() || stub_caller) failed: expected a stub-caller
Reviewed-by: sspitsyn
Backport-of: ea49537726
2025-01-10 15:27:09 +00:00
Erik Gahlin
c61fbfd6ea 8345337: JFR: jfr view should display all direct subfields for an event type
Reviewed-by: mgronlun
Backport-of: 672c413c61
2025-01-10 13:51:45 +00:00
Fei Yang
92a4e23467 8346838: RISC-V: runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java crash with debug VMs
Reviewed-by: rehn
Backport-of: 379ac349d1
2025-01-10 10:45:42 +00:00
Fredrik Bredberg
ba36d309c3 8332506: SIGFPE In ObjectSynchronizer::is_async_deflation_needed()
Reviewed-by: coleenp
Backport-of: cbabc04515
2025-01-10 08:56:45 +00:00
Aleksey Shipilev
41630c5c32 8347127: CTW fails to build after JDK-8334733
Reviewed-by: phh
Backport-of: e413fc643c
2025-01-10 08:43:03 +00:00
Weijun Wang
864d0fde23 8347289: HKDF delayed provider selection failed with non-extractable PRK
Reviewed-by: valeriep
Backport-of: db7fa6a2c6
2025-01-09 20:44:54 +00:00
William Kemper
ff9b8e4607 8346737: GenShen: Generational memory pools should not report zero for maximum capacity
Reviewed-by: kdnilsen, ysr
Backport-of: 249f141211
2025-01-09 17:07:14 +00:00
Severin Gehwolf
7d4fa7818b 8345259: Disallow ALL-MODULE-PATH without explicit --module-path
Reviewed-by: alanb, mchung
Backport-of: bcb1bdaae7
2025-01-09 10:04:19 +00:00
Severin Gehwolf
c033806b8c 8346739: jpackage tests failed after JDK-8345259
Reviewed-by: shade, mchung, asemenyuk
Backport-of: 7ba969a576
2025-01-09 10:03:54 +00:00
Alexey Semenyuk
bf45128055 8346872: tools/jpackage/windows/WinLongPathTest.java fails
Reviewed-by: almatvee
Backport-of: 4d18e5a1e2
2025-01-09 03:45:05 +00:00
Calvin Cheung
29c6bf23fb 8346457: AOT cache creation crashes with "assert(pair_at(i).match() < pair_at(i+1).match()) failed: unsorted table entries"
Reviewed-by: iklam
Backport-of: 8d388ccd9e
2025-01-08 23:30:52 +00:00
SendaoYan
c3b52089f6 8346965: Multiple compiler/ciReplay test fails with -XX:+SegmentedCodeCache
Reviewed-by: epeter
Backport-of: cf3e48e771
2025-01-08 15:24:09 +00:00
Per Minborg
860b30ddf9 8347047: Cleanup action passed to MemorySegment::reinterpret keeps old segment alive
Reviewed-by: shade
Backport-of: b0c935c03e
2025-01-08 10:16:28 +00:00
Tobias Hartmann
256856a5a1 8343747: C2: TestReplicateAtConv.java crashes with -XX:MaxVectorSize=8
Reviewed-by: chagedorn
Backport-of: 874d68a96c
2025-01-07 09:49:56 +00:00
William Kemper
cc7c293bce 8345970: pthread_getcpuclockid related crashes in shenandoah tests
Reviewed-by: shade
Backport-of: 2ce53e8848
2025-01-06 18:24:37 +00:00
Sorna Sarathi N
33971ecb6e 8346069: Add missing Classpath exception statements
Reviewed-by: kcr, iris, amitkumar
Backport-of: 09c29d1d42
2025-01-06 13:27:11 +00:00
Amit Kumar
4254e99ce2 8346847: [s390x] minimal build failure
Reviewed-by: clanger
Backport-of: 807f6f7fb8
2024-12-31 06:26:39 +00:00
Nizar Benalla
05c3769986 8337111: Bad HTML checker for generated documentation
8337113: Bad character checker for generated documentation
8337116: Internal links checker for generated documentation
8337114: DocType checker for generated documentation
8337117: External links checker for generated documentation

Reviewed-by: prappo
Backport-of: ed292318a9
2024-12-30 11:26:02 +00:00
Nizar Benalla
ab78b04cf6 8346667: Doccheck: warning about missing </span> before <h2>
Reviewed-by: prappo
Backport-of: 054c644ea6
2024-12-30 10:59:08 +00:00
Sorna Sarathi N
bed040191b 8344611: Add missing classpath exception
Reviewed-by: iris
Backport-of: 458979d83a
2024-12-20 18:13:13 +00:00
Patricio Chilano Mateo
5d138cbba0 8345266: java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java JTREG_TEST_THREAD_FACTORY=Virtual fails with OOME
Reviewed-by: dholmes, alanb
Backport-of: 572ce269d0
2024-12-20 15:26:22 +00:00
Nizar Benalla
63aa68a7c6 8346128: Comparison build fails due to difference in LabelTarget.html
Reviewed-by: hannesw, liach
Backport-of: 2a68f74188
2024-12-20 15:05:22 +00:00
Justin Lu
f0ada9f34e 8345327: JDK 24 RDP1 L10n resource files update
Reviewed-by: naoto, dnguyen
Backport-of: fd0207d593
2024-12-19 22:08:57 +00:00
Hamlin Li
303736b038 8345669: RISC-V: fix client build failure due to AlignVector after JDK-8343827
Reviewed-by: fyang
Backport-of: a24b08fcb0
2024-12-19 09:27:16 +00:00
David Holmes
2c336299aa 8321818: vmTestbase/nsk/stress/strace/strace015.java failed with 'Cannot read the array length because "<local4>" is null'
Reviewed-by: lmesnik
Backport-of: ea50c54a14
2024-12-19 07:50:02 +00:00
SendaoYan
4aec2d4ef9 8338714: vmTestbase/nsk/jdb/kill/kill001/kill001.java fails with JTREG_TEST_THREAD_FACTORY=Virtual
Reviewed-by: dholmes
Backport-of: 414eb6bb83
2024-12-19 02:47:52 +00:00
Daniel Fuchs
b8249c5d90 8346017: Socket.connect specified to throw UHE for unresolved address is problematic for SOCKS V5 proxy
Reviewed-by: alanb
Backport-of: 9e8aa855fe
2024-12-18 18:05:16 +00:00
Paul Sandoz
0225372e0b 8346174: UMAX/UMIN are missing from XXXVector::reductionOperations
Reviewed-by: jbhateja
Backport-of: 31c3b19174
2024-12-18 17:23:51 +00:00
Jan Lahoda
2cc14faa21 8344647: Make java.se participate in the preview language feature requires transitive java.base
Reviewed-by: liach, vromero
Backport-of: d50b725ac0
2024-12-18 13:45:44 +00:00
Lance Andersen
f703b6e7b1 8346202: Correct typo in SQLPermission
Reviewed-by: iris
Backport-of: ab1dbd4089
2024-12-16 17:07:28 +00:00
Albert Mingkun Yang
297b21fb60 8345323: Parallel GC does not handle UseLargePages and UseNUMA gracefully
Reviewed-by: sjohanss
Backport-of: a9a5f7cb0a
2024-12-16 14:57:34 +00:00
Maurizio Cimadamore
67b8251679 8345944: JEP 492: extending local class in a different static context should not be allowed
8345953: JEP 492: instantiating local classes in a different static context should not be allowed

Reviewed-by: vromero
Backport-of: 0ad64234e2
2024-12-16 10:17:28 +00:00
Severin Gehwolf
6e8aad1ad4 8345573: Module dependencies not resolved from run-time image when --limit-module is being used
Reviewed-by: mchung
Backport-of: 11cd639842
2024-12-16 09:41:59 +00:00
Ioi Lam
4d6eccd9fc 8346159: Disable CDS AOTClassLinking tests for JVMCI due to JDK-8345635
Reviewed-by: ccheung
Backport-of: c2f0ef5f48
2024-12-16 06:17:11 +00:00
Nizar Benalla
6bc14d6b77 8345888: Broken links in the JDK 24 JavaDoc API documentation, build 27
Reviewed-by: psadhukhan
Backport-of: 9bd70ec806
2024-12-13 11:25:56 +00:00
Coleen Phillimore
897a8abecc 8346040: Zero interpreter build on Linux Aarch64 is broken
Reviewed-by: kbarrett
Backport-of: ef6e987a00
2024-12-12 22:24:36 +00:00
Roger Riggs
3b53ed7fb0 8345818: Fix SM cleanup of parsing of System property resource.bundle.debug
Reviewed-by: lancea
Backport-of: 4f855d1342
2024-12-12 17:27:54 +00:00
Adam Sotona
6fdfa72996 8345773: Class-File API debug printing capability
Reviewed-by: liach
Backport-of: f88c1c6ff8
2024-12-12 13:37:00 +00:00
Coleen Phillimore
950c8adfd7 8340212: -Xshare:off -XX:CompressedClassSpaceBaseAddress=0x40001000000 crashes on macos-aarch64
Reviewed-by: iklam
Backport-of: a6277bb521
2024-12-11 17:16:13 +00:00
Chen Liang
03bdee0f75 8342469: Improve API documentation for java.lang.classfile.instruction
Reviewed-by: asotona
Backport-of: 0f035545e5
2024-12-11 16:06:40 +00:00
Kevin Driver
4ecb28ccdc 8344924: Default CA certificates loaded despite request to use custom keystore
Reviewed-by: mullan
Backport-of: 4c39e9faa0
2024-12-10 21:14:37 +00:00
Michael McMahon
ba02e0bd1b 8345794: Backout doc change introduced by JDK-8235786
Reviewed-by: dfuchs
Backport-of: eff20a38c7
2024-12-10 16:58:13 +00:00
Per Minborg
253030a6d4 8345465: Fix performance regression on x64 after JDK-8345120
Reviewed-by: jvernee
Backport-of: 06c44dd568
2024-12-10 14:22:42 +00:00
Chen Liang
a81325433d 8334733: Remove obsolete @enablePreview from tests after JDK-8334714
Reviewed-by: mchung
Backport-of: 4966419550
2024-12-09 18:35:16 +00:00
Magnus Ihse Bursie
203422a8ed 8345424: Move FindDebuginfoFiles out of FileUtils.gmk
Reviewed-by: erikj
Backport-of: 5f30a8d90c
2024-12-09 15:57:55 +00:00
Fernando Guallini
8e9ba788ae 8345414: Google CAInterop test failures
Reviewed-by: rhalade
2024-12-06 18:41:47 +00:00
Matias Saavedra Silva
3aa07dbf14 8343890: SEGV crash in RunTimeClassInfo::klass
Reviewed-by: ccheung
Backport-of: bf0debc023
2024-12-05 22:01:31 +00:00
793 changed files with 18730 additions and 5277 deletions

View File

@@ -29,6 +29,7 @@ include $(SPEC)
include MakeBase.gmk
include CopyFiles.gmk
include DebugInfoUtils.gmk
include Execute.gmk
include Modules.gmk
include Utils.gmk

View File

@@ -29,6 +29,7 @@ include $(SPEC)
include MakeBase.gmk
include CopyFiles.gmk
include DebugInfoUtils.gmk
include Modules.gmk
include modules/LauncherCommon.gmk

View File

@@ -0,0 +1,58 @@
#
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
ifeq ($(_MAKEBASE_GMK), )
$(error You must include MakeBase.gmk prior to including DebugInfoUtils.gmk)
endif
################################################################################
#
# Common debuginfo utility functions
#
################################################################################
################################################################################
# Find native debuginfo files in a directory
#
# Param 1 - dir to find debuginfo files in
FindDebuginfoFiles = \
$(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
# Pick the correct debug info files to copy, either zipped or not.
ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
DEBUGINFO_SUFFIXES += .diz
else
DEBUGINFO_SUFFIXES := .debuginfo .pdb .map
# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
# dirs.
ifeq ($(call isTargetOs, macosx), true)
$(call FillFindCache, \
$(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds)
FindDebuginfoFiles = \
$(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1)))
endif
endif

View File

@@ -307,26 +307,3 @@ ifeq ($(DISABLE_CACHE_FIND), true)
else
FindFiles = $(CacheFindFiles)
endif
# Find native debuginfo files in a directory
#
# Param 1 - dir to find debuginfo files in
FindDebuginfoFiles = \
$(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
# Pick the correct debug info files to copy, either zipped or not.
ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
DEBUGINFO_SUFFIXES += .diz
else
DEBUGINFO_SUFFIXES := .debuginfo .pdb .map
# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
# dirs.
ifeq ($(call isTargetOs, macosx), true)
$(call FillFindCache, \
$(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds)
FindDebuginfoFiles = \
$(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1)))
endif
endif

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2021, 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
@@ -64,7 +64,7 @@ ifeq ($(call isTargetOs, linux)+$(call isTargetCpu, aarch64)+$(INCLUDE_COMPILER2
EXTRA_SRC := libsleef/generated, \
DISABLED_WARNINGS_gcc := unused-function sign-compare tautological-compare ignored-qualifiers, \
DISABLED_WARNINGS_clang := unused-function sign-compare tautological-compare ignored-qualifiers, \
CFLAGS := $(SVE_CFLAGS), \
vector_math_sve.c_CFLAGS := $(SVE_CFLAGS), \
))
TARGETS += $(BUILD_LIBSLEEF)

View File

@@ -24,12 +24,14 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/macroAssembler.hpp"
#include "logging/log.hpp"
#include "oops/compressedKlass.hpp"
#include "memory/metaspace.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/formatBuffer.hpp"
// Helper function; reserve at an address that is compatible with EOR
static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
@@ -79,6 +81,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
}
return result;
}
char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size_t size, bool aslr, bool optimize_for_zero_base) {
char* result = nullptr;
@@ -117,3 +120,12 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
return result;
}
bool CompressedKlassPointers::check_klass_decode_mode(address base, int shift, const size_t range) {
return MacroAssembler::check_klass_decode_mode(base, shift, range);
}
bool CompressedKlassPointers::set_klass_decode_mode() {
const size_t range = klass_range_end() - base();
return MacroAssembler::set_klass_decode_mode(_base, _shift, range);
}

View File

@@ -5291,32 +5291,47 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
MacroAssembler::KlassDecodeMode MacroAssembler::_klass_decode_mode(KlassDecodeNone);
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() {
assert(UseCompressedClassPointers, "not using compressed class pointers");
assert(Metaspace::initialized(), "metaspace not initialized yet");
assert(_klass_decode_mode != KlassDecodeNone, "should be initialized");
return _klass_decode_mode;
}
if (_klass_decode_mode != KlassDecodeNone) {
return _klass_decode_mode;
}
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) {
assert(UseCompressedClassPointers, "not using compressed class pointers");
if (CompressedKlassPointers::base() == nullptr) {
return (_klass_decode_mode = KlassDecodeZero);
// KlassDecodeMode shouldn't be set already.
assert(_klass_decode_mode == KlassDecodeNone, "set once");
if (base == nullptr) {
return KlassDecodeZero;
}
if (operand_valid_for_logical_immediate(
/*is32*/false, (uint64_t)CompressedKlassPointers::base())) {
const size_t range = CompressedKlassPointers::klass_range_end() - CompressedKlassPointers::base();
/*is32*/false, (uint64_t)base)) {
const uint64_t range_mask = right_n_bits(log2i_ceil(range));
if (((uint64_t)CompressedKlassPointers::base() & range_mask) == 0) {
return (_klass_decode_mode = KlassDecodeXor);
if (((uint64_t)base & range_mask) == 0) {
return KlassDecodeXor;
}
}
const uint64_t shifted_base =
(uint64_t)CompressedKlassPointers::base() >> CompressedKlassPointers::shift();
guarantee((shifted_base & 0xffff0000ffffffff) == 0,
"compressed class base bad alignment");
(uint64_t)base >> shift;
if ((shifted_base & 0xffff0000ffffffff) == 0) {
return KlassDecodeMovk;
}
return (_klass_decode_mode = KlassDecodeMovk);
// No valid encoding.
return KlassDecodeNone;
}
// Check if one of the above decoding modes will work for given base, shift and range.
bool MacroAssembler::check_klass_decode_mode(address base, int shift, const size_t range) {
return klass_decode_mode(base, shift, range) != KlassDecodeNone;
}
bool MacroAssembler::set_klass_decode_mode(address base, int shift, const size_t range) {
_klass_decode_mode = klass_decode_mode(base, shift, range);
return _klass_decode_mode != KlassDecodeNone;
}
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {

View File

@@ -94,11 +94,22 @@ class MacroAssembler: public Assembler {
KlassDecodeMovk
};
KlassDecodeMode klass_decode_mode();
// Calculate decoding mode based on given parameters, used for checking then ultimately setting.
static KlassDecodeMode klass_decode_mode(address base, int shift, const size_t range);
private:
static KlassDecodeMode _klass_decode_mode;
// Returns above setting with asserts
static KlassDecodeMode klass_decode_mode();
public:
// Checks the decode mode and returns false if not compatible with preferred decoding mode.
static bool check_klass_decode_mode(address base, int shift, const size_t range);
// Sets the decode mode and returns false if cannot be set.
static bool set_klass_decode_mode(address base, int shift, const size_t range);
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}

View File

@@ -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 :

View File

@@ -154,10 +154,6 @@ void VM_Version::common_initialize() {
unaligned_access.value() != MISALIGNED_FAST);
}
if (FLAG_IS_DEFAULT(AlignVector)) {
FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses);
}
// See JDK-8026049
// This machine has fast unaligned memory accesses
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
@@ -440,6 +436,10 @@ void VM_Version::c2_initialize() {
warning("AES/CTR intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
}
if (FLAG_IS_DEFAULT(AlignVector)) {
FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses);
}
}
#endif // COMPILER2

View File

@@ -308,6 +308,12 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
}
// The OptoScheduling information is not maintained in s390.ad.
if (OptoScheduling) {
warning("OptoScheduling is not supported on this CPU.");
FLAG_SET_DEFAULT(OptoScheduling, false);
}
#endif
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
FLAG_SET_DEFAULT(UsePopCountInstruction, true);
@@ -323,12 +329,6 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
FLAG_SET_DEFAULT(UseUnalignedAccesses, true);
}
// The OptoScheduling information is not maintained in s390.ad.
if (OptoScheduling) {
warning("OptoScheduling is not supported on this CPU.");
FLAG_SET_DEFAULT(OptoScheduling, false);
}
}

View File

@@ -38,7 +38,7 @@ enum platform_dependent_constants {
// AVX512 intrinsics add more code in 64-bit VM,
// Windows have more code to save/restore registers
_compiler_stubs_code_size = 20000 LP64_ONLY(+47000) WINDOWS_ONLY(+2000),
_final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+2000) ZGC_ONLY(+20000)
_final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)
};
class x86 {

View File

@@ -145,15 +145,16 @@ size_t MetaspaceShared::core_region_alignment() {
}
static bool shared_base_valid(char* shared_base) {
// We check user input for SharedBaseAddress at dump time. We must weed out values
// we already know to be invalid later.
// We check user input for SharedBaseAddress at dump time.
// At CDS runtime, "shared_base" will be the (attempted) mapping start. It will also
// be the encoding base, since the the headers of archived base objects (and with Lilliput,
// the prototype mark words) carry pre-computed narrow Klass IDs that refer to the mapping
// start as base.
//
// Therefore, "shared_base" must be later usable as encoding base.
// On AARCH64, The "shared_base" may not be later usable as encoding base, depending on the
// total size of the reserved area and the precomputed_narrow_klass_shift. This is checked
// before reserving memory. Here we weed out values already known to be invalid later.
return AARCH64_ONLY(is_aligned(shared_base, 4 * G)) NOT_AARCH64(true);
}
@@ -985,8 +986,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 {
@@ -1486,6 +1489,15 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
const size_t total_range_size =
archive_space_size + gap_size + class_space_size;
// Test that class space base address plus shift can be decoded by aarch64, when restored.
const int precomputed_narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
if (!CompressedKlassPointers::check_klass_decode_mode(base_address, precomputed_narrow_klass_shift,
total_range_size)) {
log_info(cds)("CDS initialization: Cannot use SharedBaseAddress " PTR_FORMAT " with precomputed shift %d.",
p2i(base_address), precomputed_narrow_klass_shift);
use_archive_base_addr = false;
}
assert(total_range_size > ccs_begin_offset, "must be");
if (use_windows_memory_mapping() && use_archive_base_addr) {
if (base_address != nullptr) {
@@ -1525,7 +1537,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
}
// Paranoid checks:
assert(base_address == nullptr || (address)total_space_rs.base() == base_address,
assert(!use_archive_base_addr || (address)total_space_rs.base() == base_address,
"Sanity (" PTR_FORMAT " vs " PTR_FORMAT ")", p2i(base_address), p2i(total_space_rs.base()));
assert(is_aligned(total_space_rs.base(), base_address_alignment), "Sanity");
assert(total_space_rs.size() == total_range_size, "Sanity");

View File

@@ -76,10 +76,13 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) {
}
InstanceKlass* RunTimeClassInfo::klass() const {
if (ArchiveBuilder::is_active() && ArchiveBuilder::current()->is_in_buffer_space((address)this)) {
return ArchiveBuilder::current()->offset_to_buffered<InstanceKlass*>(_klass_offset);
} else {
if (MetaspaceShared::is_in_shared_metaspace(this)) {
// <this> is inside a mmaped CDS archive.
return ArchiveUtils::offset_to_archived_address<InstanceKlass*>(_klass_offset);
} else {
// <this> is a temporary copy of a RunTimeClassInfo that's being initialized
// by the ArchiveBuilder.
return ArchiveBuilder::current()->offset_to_buffered<InstanceKlass*>(_klass_offset);
}
}

View File

@@ -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
@@ -205,7 +205,7 @@ void CodeCache::initialize_heaps() {
const bool cache_size_set = FLAG_IS_CMDLINE(ReservedCodeCacheSize);
const size_t ps = page_size(false, 8);
const size_t min_size = MAX2(os::vm_allocation_granularity(), ps);
const size_t min_cache_size = CompilerConfig::min_code_cache_size(); // Make sure we have enough space for VM internal code
const size_t min_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); // Make sure we have enough space for VM internal code
size_t cache_size = align_up(ReservedCodeCacheSize, min_size);
// Prerequisites

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 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
@@ -455,7 +455,7 @@ void CompilationPolicy::initialize() {
c2_size = C2Compiler::initial_code_buffer_size();
#endif
size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3);
int max_count = (ReservedCodeCacheSize - (int)CompilerConfig::min_code_cache_size()) / (int)buffer_size;
int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size;
if (count > max_count) {
// Lower the compiler count such that all buffers fit into the code cache
count = MAX2(max_count, c1_only ? 1 : 2);

View File

@@ -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
@@ -475,7 +475,8 @@ void CompilerConfig::set_jvmci_specific_flags() {
bool CompilerConfig::check_args_consistency(bool status) {
// Check lower bounds of the code cache
size_t min_code_cache_size = CompilerConfig::min_code_cache_size();
// Template Interpreter code is approximately 3X larger in debug builds.
uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
if (ReservedCodeCacheSize < InitialCodeCacheSize) {
jio_fprintf(defaultStream::error_stream(),
"Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n",

View File

@@ -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
@@ -148,8 +148,6 @@ public:
inline static bool is_c2_or_jvmci_compiler_only();
inline static bool is_c2_or_jvmci_compiler_enabled();
inline static size_t min_code_cache_size();
private:
static bool is_compilation_mode_selected();
static void set_compilation_policy_flags();

View File

@@ -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
@@ -25,12 +25,6 @@
#ifndef SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
#define SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
#ifdef COMPILER2
#include "opto/c2compiler.hpp"
#endif
#include "compiler/compilerDefinitions.hpp"
#include "compiler/compiler_globals.hpp"
@@ -138,13 +132,4 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_enabled() {
return is_c2_enabled() || is_jvmci_compiler_enabled();
}
inline size_t CompilerConfig::min_code_cache_size() {
size_t min_code_cache_size = CodeCacheMinimumUseSpace;
// Template Interpreter code is approximately 3X larger in debug builds.
DEBUG_ONLY(min_code_cache_size *= 3);
COMPILER1_PRESENT(min_code_cache_size += Compiler::code_buffer_size());
COMPILER2_PRESENT(min_code_cache_size += C2Compiler::initial_code_buffer_size());
return min_code_cache_size;
}
#endif // SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP

View File

@@ -140,8 +140,8 @@ void VM_GC_Operation::doit_epilogue() {
}
bool VM_GC_HeapInspection::doit_prologue() {
if (_full_gc && UseZGC) {
// ZGC cannot perform a synchronous GC cycle from within the VM thread.
if (_full_gc && (UseZGC || UseShenandoahGC)) {
// ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread.
// So VM_GC_HeapInspection::collect() is a noop. To respect the _full_gc
// flag a synchronous GC cycle is performed from the caller thread in the
// prologue.

View File

@@ -37,7 +37,11 @@ size_t MinNewSize = 0;
size_t MinOldSize = 0;
size_t MaxOldSize = 0;
size_t OldSize = 0;
// If InitialHeapSize or MinHeapSize is not set on cmdline, this variable,
// together with NewSize, is used to derive them.
// Using the same value when it was a configurable flag to avoid breakage.
// See more in JDK-8346005
size_t OldSize = ScaleForWordSize(4*M);
size_t GenAlignment = 0;

View File

@@ -180,8 +180,8 @@ void ShenandoahGenerationalHeap::gc_threads_do(ThreadClosure* tcl) const {
}
void ShenandoahGenerationalHeap::stop() {
regulator_thread()->stop();
ShenandoahHeap::stop();
regulator_thread()->stop();
}
void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) {

View File

@@ -538,7 +538,6 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
_pacer(nullptr),
_verifier(nullptr),
_phase_timings(nullptr),
_mmu_tracker(),
_monitoring_support(nullptr),
_memory_pool(nullptr),
_stw_memory_manager("Shenandoah Pauses"),
@@ -632,6 +631,8 @@ public:
void ShenandoahHeap::post_initialize() {
CollectedHeap::post_initialize();
// Schedule periodic task to report on gc thread CPU utilization
_mmu_tracker.initialize();
MutexLocker ml(Threads_lock);
@@ -1467,6 +1468,18 @@ size_t ShenandoahHeap::max_tlab_size() const {
return ShenandoahHeapRegion::max_tlab_size_words();
}
void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) {
// These requests are ignored because we can't easily have Shenandoah jump into
// a synchronous (degenerated or full) cycle while it is in the middle of a concurrent
// cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly
// on the VM thread, but this would confuse the control thread mightily and doesn't
// seem worth the trouble. Instead, we will have the caller thread run (and wait for) a
// concurrent cycle in the prologue of the heap inspect/dump operation. This is how
// other concurrent collectors in the JVM handle this scenario as well.
assert(Thread::current()->is_VM_thread(), "Should be the VM thread");
guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause");
}
void ShenandoahHeap::collect(GCCause::Cause cause) {
control_thread()->request_gc(cause);
}
@@ -1547,7 +1560,9 @@ void ShenandoahHeap::set_active_generation() {
void ShenandoahHeap::on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation) {
shenandoah_policy()->record_collection_cause(cause);
assert(gc_cause() == GCCause::_no_gc, "Over-writing cause");
const GCCause::Cause current = gc_cause();
assert(current == GCCause::_no_gc, "Over-writing cause: %s, with: %s",
GCCause::to_string(current), GCCause::to_string(cause));
assert(_gc_generation == nullptr, "Over-writing _gc_generation");
set_gc_cause(cause);
@@ -2084,6 +2099,9 @@ void ShenandoahHeap::stop() {
// Step 0. Notify policy to disable event recording and prevent visiting gc threads during shutdown
_shenandoah_policy->record_shutdown();
// Step 0a. Stop reporting on gc thread cpu utilization
mmu_tracker()->stop();
// Step 1. Notify control thread that we are in shutdown.
// Note that we cannot do that with stop(), because stop() is blocking and waits for the actual shutdown.
// Doing stop() here would wait for the normal GC cycle to complete, never falling through to cancel below.

View File

@@ -608,6 +608,7 @@ public:
MemRegion reserved_region() const { return _reserved; }
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
void collect_as_vm_thread(GCCause::Cause cause) override;
void collect(GCCause::Cause cause) override;
void do_full_collection(bool clear_all_soft_refs) override;

View File

@@ -93,11 +93,6 @@ size_t ShenandoahGenerationalMemoryPool::used_in_bytes() {
return _generation->used();
}
size_t ShenandoahGenerationalMemoryPool::max_size() const {
return _generation->max_capacity();
}
ShenandoahYoungGenMemoryPool::ShenandoahYoungGenMemoryPool(ShenandoahHeap* heap) :
ShenandoahGenerationalMemoryPool(heap,
"Shenandoah Young Gen",

View File

@@ -55,7 +55,6 @@ public:
explicit ShenandoahGenerationalMemoryPool(ShenandoahHeap* heap, const char* name, ShenandoahGeneration* generation);
MemoryUsage get_memory_usage() override;
size_t used_in_bytes() override;
size_t max_size() const override;
};
class ShenandoahYoungGenMemoryPool : public ShenandoahGenerationalMemoryPool {

View File

@@ -48,6 +48,7 @@ class ThreadTimeAccumulator : public ThreadClosure {
size_t total_time;
ThreadTimeAccumulator() : total_time(0) {}
void do_thread(Thread* thread) override {
assert(!thread->has_terminated(), "Cannot get cpu time for terminated thread: " UINTX_FORMAT, thread->osthread()->thread_id_for_printing());
total_time += os::thread_cpu_time(thread);
}
};
@@ -65,7 +66,6 @@ ShenandoahMmuTracker::ShenandoahMmuTracker() :
}
ShenandoahMmuTracker::~ShenandoahMmuTracker() {
_mmu_periodic_task->disenroll();
delete _mmu_periodic_task;
}
@@ -175,6 +175,10 @@ void ShenandoahMmuTracker::report() {
log_debug(gc)("Periodic Sample: GCU = %.3f%%, MU = %.3f%% during most recent %.1fs", gcu * 100, mu * 100, time_delta);
}
void ShenandoahMmuTracker::stop() const {
_mmu_periodic_task->disenroll();
}
void ShenandoahMmuTracker::initialize() {
// initialize static data
_active_processors = os::initial_active_processor_count();

View File

@@ -101,6 +101,10 @@ public:
// GCPauseIntervalMillis and defaults to 5 seconds. This method computes
// the MMU over the elapsed interval and records it in a running average.
void report();
// Unenrolls the periodic task that collects CPU utilization for GC threads. This must happen _before_ the
// gc threads are stopped and terminated.
void stop() const;
};
#endif //SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP

View File

@@ -30,6 +30,7 @@
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
@@ -176,6 +177,12 @@ void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t
calc_lowest_highest_narrow_klass_id();
// This has already been checked for SharedBaseAddress and if this fails, it's a bug in the allocation code.
if (!set_klass_decode_mode()) {
fatal("base=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
p2i(_base), _shift);
}
DEBUG_ONLY(sanity_check_after_initialization();)
}
@@ -267,6 +274,20 @@ void CompressedKlassPointers::initialize(address addr, size_t len) {
calc_lowest_highest_narrow_klass_id();
// Initialize klass decode mode and check compability with decode instructions
if (!set_klass_decode_mode()) {
// Give fatal error if this is a specified address
if ((address)CompressedClassSpaceBaseAddress == _base) {
vm_exit_during_initialization(
err_msg("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
CompressedClassSpaceBaseAddress, _shift));
} else {
// If this fails, it's a bug in the allocation code.
fatal("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
p2i(_base), _shift);
}
}
#ifdef ASSERT
sanity_check_after_initialization();
#endif

View File

@@ -258,6 +258,15 @@ public:
is_aligned(addr, klass_alignment_in_bytes());
}
#if defined(AARCH64) && !defined(ZERO)
// Check that with the given base, shift and range, aarch64 code can encode and decode the klass pointer.
static bool check_klass_decode_mode(address base, int shift, const size_t range);
// Called after initialization.
static bool set_klass_decode_mode();
#else
static bool check_klass_decode_mode(address base, int shift, const size_t range) { return true; }
static bool set_klass_decode_mode() { return true; }
#endif
};
#endif // SHARE_OOPS_COMPRESSEDKLASS_HPP

View File

@@ -395,159 +395,9 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) {
}
}
// Convert a + a + ... + a into a*n
Node* serial_additions = convert_serial_additions(phase, bt);
if (serial_additions != nullptr) {
return serial_additions;
}
return AddNode::Ideal(phase, can_reshape);
}
// Try to convert a serial of additions into a single multiplication. Also convert `(a * CON) + a` to `(CON + 1) * a` as
// a side effect. On success, a new MulNode is returned.
Node* AddNode::convert_serial_additions(PhaseGVN* phase, BasicType bt) {
// We need to make sure that the current AddNode is not part of a MulNode that has already been optimized to a
// power-of-2 addition (e.g., 3 * a => (a << 2) + a). Without this check, GVN would keep trying to optimize the same
// node and can't progress. For example, 3 * a => (a << 2) + a => 3 * a => (a << 2) + a => ...
if (find_power_of_two_addition_pattern(this, bt, nullptr) != nullptr) {
return nullptr;
}
Node* in1 = in(1);
Node* in2 = in(2);
jlong multiplier;
// While multiplications can be potentially optimized to power-of-2 subtractions (e.g., a * 7 => (a << 3) - a),
// (x - y) + y => x is already handled by the Identity() methods. So, we don't need to check for that pattern here.
if (find_simple_addition_pattern(in1, bt, &multiplier) == in2
|| find_simple_lshift_pattern(in1, bt, &multiplier) == in2
|| find_simple_multiplication_pattern(in1, bt, &multiplier) == in2
|| find_power_of_two_addition_pattern(in1, bt, &multiplier) == in2) {
multiplier++; // +1 for the in2 term
Node* con = (bt == T_INT)
? (Node*) phase->intcon((jint) multiplier) // intentional type narrowing to allow overflow at max_jint
: (Node*) phase->longcon(multiplier);
return MulNode::make(con, in2, bt);
}
return nullptr;
}
// Try to match `a + a`. On success, return `a` and set `2` as `multiplier`.
// The method matches `n` for pattern: AddNode(a, a).
Node* AddNode::find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier) {
if (n->Opcode() == Op_Add(bt) && n->in(1) == n->in(2)) {
*multiplier = 2;
return n->in(1);
}
return nullptr;
}
// Try to match `a << CON`. On success, return `a` and set `1 << CON` as `multiplier`.
// Match `n` for pattern: LShiftNode(a, CON).
// Note that the power-of-2 multiplication optimization could potentially convert a MulNode to this pattern.
Node* AddNode::find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier) {
// Note that power-of-2 multiplication optimization could potentially convert a MulNode to this pattern
if (n->Opcode() == Op_LShift(bt) && n->in(2)->is_Con()) {
Node* con = n->in(2);
if (con->is_top()) {
return nullptr;
}
*multiplier = ((jlong) 1 << con->get_int());
return n->in(1);
}
return nullptr;
}
// Try to match `CON * a`. On success, return `a` and set `CON` as `multiplier`.
// Match `n` for patterns:
// - MulNode(CON, a)
// - MulNode(a, CON)
Node* AddNode::find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier) {
// This optimization technically only produces MulNode(CON, a), but we might as match MulNode(a, CON), too.
if (n->Opcode() == Op_Mul(bt) && (n->in(1)->is_Con() || n->in(2)->is_Con())) {
Node* con = n->in(1);
Node* base = n->in(2);
// swap ConNode to lhs for easier matching
if (!con->is_Con()) {
swap(con, base);
}
if (con->is_top()) {
return nullptr;
}
*multiplier = con->get_integer_as_long(bt);
return base;
}
return nullptr;
}
// Try to match `(a << CON1) + (a << CON2)`. On success, return `a` and set `(1 << CON1) + (1 << CON2)` as `multiplier`.
// Match `n` for patterns:
// - AddNode(LShiftNode(a, CON), LShiftNode(a, CON)/a)
// - AddNode(LShiftNode(a, CON)/a, LShiftNode(a, CON))
// given that lhs is different from rhs.
// Note that one of the term of the addition could simply be `a` (i.e., a << 0). Calling this function with `multiplier`
// being null is safe.
Node* AddNode::find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier) {
if (n->Opcode() == Op_Add(bt) && n->in(1) != n->in(2)) {
Node* lhs = n->in(1);
Node* rhs = n->in(2);
// swap LShiftNode to lhs for easier matching
if (lhs->Opcode() != Op_LShift(bt)) {
swap(lhs, rhs);
}
// AddNode(LShiftNode(a, CON), *)?
if (lhs->Opcode() != Op_LShift(bt) || !lhs->in(2)->is_Con()) {
return nullptr;
}
jlong lhs_multiplier = 0;
if (multiplier != nullptr) {
Node* con = lhs->in(2);
if (con->is_top()) {
return nullptr;
}
lhs_multiplier = (jlong) 1 << con->get_int();
}
// AddNode(LShiftNode(a, CON), a)?
if (lhs->in(1) == rhs) {
if (multiplier != nullptr) {
*multiplier = lhs_multiplier + 1;
}
return rhs;
}
// AddNode(LShiftNode(a, CON), LShiftNode(a, CON2))?
if (rhs->Opcode() == Op_LShift(bt) && lhs->in(1) == rhs->in(1) && rhs->in(2)->is_Con()) {
if (multiplier != nullptr) {
Node* con = rhs->in(2);
if (con->is_top()) {
return nullptr;
}
*multiplier = lhs_multiplier + ((jlong) 1 << con->get_int());
}
return lhs->in(1);
}
return nullptr;
}
return nullptr;
}
Node* AddINode::Ideal(PhaseGVN* phase, bool can_reshape) {
Node* in1 = in(1);

View File

@@ -42,13 +42,6 @@ typedef const Pair<Node*, jint> ConstAddOperands;
// by virtual functions.
class AddNode : public Node {
virtual uint hash() const;
Node* convert_serial_additions(PhaseGVN* phase, BasicType bt);
static Node* find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier);
static Node* find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier);
static Node* find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier);
static Node* find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier);
public:
AddNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {
init_class_id(Class_Add);

View File

@@ -933,6 +933,9 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
// Make the hot call:
JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
if (kit.failing()) {
return nullptr;
}
if (new_jvms == nullptr) {
// Inline failed, so make a direct call.
assert(_if_hit->is_inline(), "must have been a failed inline");
@@ -1260,6 +1263,9 @@ JVMState* PredicatedIntrinsicGenerator::generate(JVMState* jvms) {
PreserveJVMState pjvms(&kit);
// Generate intrinsic code:
JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
if (kit.failing()) {
return nullptr;
}
if (new_jvms == nullptr) {
// Intrinsic failed, use normal compilation path for this predicate.
slow_region->add_req(kit.control());

View File

@@ -4262,7 +4262,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
//---------------------generate_array_guard_common------------------------
Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
bool obj_array, bool not_array) {
bool obj_array, bool not_array, Node** obj) {
if (stopped()) {
return nullptr;
@@ -4304,7 +4304,19 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
// invert the test if we are looking for a non-array
if (not_array) btest = BoolTest(btest).negate();
Node* bol = _gvn.transform(new BoolNode(cmp, btest));
return generate_fair_guard(bol, region);
Node* ctrl = generate_fair_guard(bol, region);
Node* is_array_ctrl = not_array ? control() : ctrl;
if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) {
// Keep track of the fact that 'obj' is an array to prevent
// array specific accesses from floating above the guard.
Node* cast = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
// Check for top because in rare cases, the type system can determine that
// the object can't be an array but the layout helper check is not folded.
if (!cast->is_top()) {
*obj = cast;
}
}
return ctrl;
}
@@ -4399,7 +4411,7 @@ bool LibraryCallKit::inline_native_getLength() {
if (stopped()) return true;
// Deoptimize if it is a non-array.
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr);
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr, &array);
if (non_array != nullptr) {
PreserveJVMState pjvms(this);
@@ -5259,12 +5271,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
record_for_igvn(result_reg);
Node* obj_klass = load_object_klass(obj);
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr);
Node* array_obj = obj;
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr, &array_obj);
if (array_ctl != nullptr) {
// It's an array.
PreserveJVMState pjvms(this);
set_control(array_ctl);
Node* obj_length = load_array_length(obj);
Node* obj_length = load_array_length(array_obj);
Node* array_size = nullptr; // Size of the array without object alignment padding.
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true);
@@ -5278,7 +5291,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
set_control(is_obja);
// Generate a direct call to the right arraycopy function(s).
// Clones are always tightly coupled.
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, array_obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
ac->set_clone_oop_array();
Node* n = _gvn.transform(ac);
assert(n == ac, "cannot disappear");
@@ -5299,7 +5312,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
// the object.)
if (!stopped()) {
copy_to_clone(obj, alloc_obj, array_size, true);
copy_to_clone(array_obj, alloc_obj, array_size, true);
// Present the results of the copy.
result_reg->init_req(_array_path, control());
@@ -5920,8 +5933,8 @@ bool LibraryCallKit::inline_arraycopy() {
record_for_igvn(slow_region);
// (1) src and dest are arrays.
generate_non_array_guard(load_object_klass(src), slow_region);
generate_non_array_guard(load_object_klass(dest), slow_region);
generate_non_array_guard(load_object_klass(src), slow_region, &src);
generate_non_array_guard(load_object_klass(dest), slow_region, &dest);
// (2) src and dest arrays must have elements of the same BasicType
// done at macro expansion or at Ideal transformation time
@@ -8537,7 +8550,7 @@ bool LibraryCallKit::inline_getObjectSize() {
PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
record_for_igvn(result_reg);
Node* array_ctl = generate_array_guard(klass_node, nullptr);
Node* array_ctl = generate_array_guard(klass_node, nullptr, &obj);
if (array_ctl != nullptr) {
// Array case: size is round(header + element_size*arraylength).
// Since arraylength is different for every array instance, we have to

View File

@@ -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
@@ -106,6 +106,10 @@ class LibraryCallKit : public GraphKit {
void push_result() {
// Push the result onto the stack.
if (!stopped() && result() != nullptr) {
if (result()->is_top()) {
assert(false, "Can't determine return value.");
C->record_method_not_compilable("Can't determine return value.");
}
BasicType bt = result()->bottom_type()->basic_type();
push_node(bt, result());
}
@@ -163,20 +167,20 @@ class LibraryCallKit : public GraphKit {
RegionNode* region);
Node* generate_interface_guard(Node* kls, RegionNode* region);
Node* generate_hidden_class_guard(Node* kls, RegionNode* region);
Node* generate_array_guard(Node* kls, RegionNode* region) {
return generate_array_guard_common(kls, region, false, false);
Node* generate_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
return generate_array_guard_common(kls, region, false, false, obj);
}
Node* generate_non_array_guard(Node* kls, RegionNode* region) {
return generate_array_guard_common(kls, region, false, true);
Node* generate_non_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
return generate_array_guard_common(kls, region, false, true, obj);
}
Node* generate_objArray_guard(Node* kls, RegionNode* region) {
return generate_array_guard_common(kls, region, true, false);
Node* generate_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
return generate_array_guard_common(kls, region, true, false, obj);
}
Node* generate_non_objArray_guard(Node* kls, RegionNode* region) {
return generate_array_guard_common(kls, region, true, true);
Node* generate_non_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
return generate_array_guard_common(kls, region, true, true, obj);
}
Node* generate_array_guard_common(Node* kls, RegionNode* region,
bool obj_array, bool not_array);
bool obj_array, bool not_array, Node** obj = nullptr);
Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region);
CallJavaNode* generate_method_call(vmIntrinsicID method_id, bool is_virtual, bool is_static, bool res_not_null);
CallJavaNode* generate_method_call_static(vmIntrinsicID method_id, bool res_not_null) {

View File

@@ -1623,27 +1623,17 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) {
return new BoolNode( ncmp, _test.negate() );
}
// Change ((x & (m - 1)) u< m) into (m > 0)
// This is the off-by-one variant of ((x & m) u<= m)
if (cop == Op_CmpU &&
_test._test == BoolTest::lt &&
cmp1_op == Op_AndI) {
Node* l = cmp1->in(1);
Node* r = cmp1->in(2);
for (int repeat = 0; repeat < 2; repeat++) {
bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 &&
r->in(1) == cmp2;
if (match) {
// arraylength known to be non-negative, so a (arraylength != 0) is sufficient,
// but to be compatible with the array range check pattern, use (arraylength u> 0)
Node* ncmp = cmp2->Opcode() == Op_LoadRange
? phase->transform(new CmpUNode(cmp2, phase->intcon(0)))
: phase->transform(new CmpINode(cmp2, phase->intcon(0)));
return new BoolNode(ncmp, BoolTest::gt);
} else {
// commute and try again
l = cmp1->in(2);
r = cmp1->in(1);
// Transform: "((x & (m - 1)) <u m)" or "(((m - 1) & x) <u m)" into "(m >u 0)"
// This is case [CMPU_MASK] which is further described at the method comment of BoolNode::Value_cmpu_and_mask().
if (cop == Op_CmpU && _test._test == BoolTest::lt && cmp1_op == Op_AndI) {
Node* m = cmp2; // RHS: m
for (int add_idx = 1; add_idx <= 2; add_idx++) { // LHS: "(m + (-1)) & x" or "x & (m + (-1))"?
Node* maybe_m_minus_1 = cmp1->in(add_idx);
if (maybe_m_minus_1->Opcode() == Op_AddI &&
maybe_m_minus_1->in(2)->find_int_con(0) == -1 &&
maybe_m_minus_1->in(1) == m) {
Node* m_cmpu_0 = phase->transform(new CmpUNode(m, phase->intcon(0)));
return new BoolNode(m_cmpu_0, BoolTest::gt);
}
}
}
@@ -1809,9 +1799,57 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// }
}
//------------------------------Value------------------------------------------
// Change ((x & m) u<= m) or ((m & x) u<= m) to always true
// Same with ((x & m) u< m+1) and ((m & x) u< m+1)
// We use the following Lemmas/insights for the following two transformations (1) and (2):
// x & y <=u y, for any x and y (Lemma 1, masking always results in a smaller unsigned number)
// y <u y + 1 is always true if y != -1 (Lemma 2, (uint)(-1 + 1) == (uint)(UINT_MAX + 1) which overflows)
// y <u 0 is always false for any y (Lemma 3, 0 == UINT_MIN and nothing can be smaller than that)
//
// (1a) Always: Change ((x & m) <=u m ) or ((m & x) <=u m ) to always true (true by Lemma 1)
// (1b) If m != -1: Change ((x & m) <u m + 1) or ((m & x) <u m + 1) to always true:
// x & m <=u m is always true // (Lemma 1)
// x & m <=u m <u m + 1 is always true // (Lemma 2: m <u m + 1, if m != -1)
//
// A counter example for (1b), if we allowed m == -1:
// (x & m) <u m + 1
// (x & -1) <u 0
// x <u 0
// which is false for any x (Lemma 3)
//
// (2) Change ((x & (m - 1)) <u m) or (((m - 1) & x) <u m) to (m >u 0)
// This is the off-by-one variant of the above.
//
// We now prove that this replacement is correct. This is the same as proving
// "m >u 0" if and only if "x & (m - 1) <u m", i.e. "m >u 0 <=> x & (m - 1) <u m"
//
// We use (Lemma 1) and (Lemma 3) from above.
//
// Case "x & (m - 1) <u m => m >u 0":
// We prove this by contradiction:
// Assume m <=u 0 which is equivalent to m == 0:
// and thus
// x & (m - 1) <u m = 0 // m == 0
// y <u 0 // y = x & (m - 1)
// by Lemma 3, this is always false, i.e. a contradiction to our assumption.
//
// Case "m >u 0 => x & (m - 1) <u m":
// x & (m - 1) <=u (m - 1) // (Lemma 1)
// x & (m - 1) <=u (m - 1) <u m // Using assumption m >u 0, no underflow of "m - 1"
//
//
// Note that the signed version of "m > 0":
// m > 0 <=> x & (m - 1) <u m
// does not hold:
// Assume m == -1 and x == -1:
// x & (m - 1) <u m
// -1 & -2 <u -1
// -2 <u -1
// UINT_MAX - 1 <u UINT_MAX // Signed to unsigned numbers
// which is true while
// m > 0
// is false which is a contradiction.
//
// (1a) and (1b) is covered by this method since we can directly return a true value as type while (2) is covered
// in BoolNode::Ideal since we create a new non-constant node (see [CMPU_MASK]).
const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const {
Node* cmp = in(1);
if (cmp != nullptr && cmp->Opcode() == Op_CmpU) {
@@ -1819,14 +1857,21 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const {
Node* cmp2 = cmp->in(2);
if (cmp1->Opcode() == Op_AndI) {
Node* bound = nullptr;
Node* m = nullptr;
if (_test._test == BoolTest::le) {
bound = cmp2;
// (1a) "((x & m) <=u m)", cmp2 = m
m = cmp2;
} else if (_test._test == BoolTest::lt && cmp2->Opcode() == Op_AddI && cmp2->in(2)->find_int_con(0) == 1) {
bound = cmp2->in(1);
// (1b) "(x & m) <u m + 1" and "(m & x) <u m + 1", cmp2 = m + 1
Node* rhs_m = cmp2->in(1);
const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int();
if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) {
// Exclude any case where m == -1 is possible.
m = rhs_m;
}
}
if (cmp1->in(2) == bound || cmp1->in(1) == bound) {
if (cmp1->in(2) == m || cmp1->in(1) == m) {
return TypeInt::ONE;
}
}

View File

@@ -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
@@ -582,6 +582,7 @@ void Type::Initialize_shared(Compile* current) {
TypeAryPtr::_array_interfaces = TypeInterfaces::make(&array_interfaces);
TypeAryKlassPtr::_array_interfaces = TypeAryPtr::_array_interfaces;
TypeAryPtr::BOTTOM = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::BOTTOM, TypeInt::POS), nullptr, false, Type::OffsetBot);
TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), nullptr /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes());
TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), nullptr /*ciArrayKlass::make(o)*/, false, Type::OffsetBot);
@@ -4682,16 +4683,17 @@ bool TypeAryKlassPtr::is_meet_subtype_of_helper(const TypeKlassPtr *other, bool
//=============================================================================
// Convenience common pre-built types.
const TypeAryPtr *TypeAryPtr::RANGE;
const TypeAryPtr *TypeAryPtr::OOPS;
const TypeAryPtr *TypeAryPtr::NARROWOOPS;
const TypeAryPtr *TypeAryPtr::BYTES;
const TypeAryPtr *TypeAryPtr::SHORTS;
const TypeAryPtr *TypeAryPtr::CHARS;
const TypeAryPtr *TypeAryPtr::INTS;
const TypeAryPtr *TypeAryPtr::LONGS;
const TypeAryPtr *TypeAryPtr::FLOATS;
const TypeAryPtr *TypeAryPtr::DOUBLES;
const TypeAryPtr* TypeAryPtr::BOTTOM;
const TypeAryPtr* TypeAryPtr::RANGE;
const TypeAryPtr* TypeAryPtr::OOPS;
const TypeAryPtr* TypeAryPtr::NARROWOOPS;
const TypeAryPtr* TypeAryPtr::BYTES;
const TypeAryPtr* TypeAryPtr::SHORTS;
const TypeAryPtr* TypeAryPtr::CHARS;
const TypeAryPtr* TypeAryPtr::INTS;
const TypeAryPtr* TypeAryPtr::LONGS;
const TypeAryPtr* TypeAryPtr::FLOATS;
const TypeAryPtr* TypeAryPtr::DOUBLES;
//------------------------------make-------------------------------------------
const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset,

View File

@@ -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
@@ -1470,16 +1470,17 @@ public:
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
// Convenience common pre-built types.
static const TypeAryPtr *RANGE;
static const TypeAryPtr *OOPS;
static const TypeAryPtr *NARROWOOPS;
static const TypeAryPtr *BYTES;
static const TypeAryPtr *SHORTS;
static const TypeAryPtr *CHARS;
static const TypeAryPtr *INTS;
static const TypeAryPtr *LONGS;
static const TypeAryPtr *FLOATS;
static const TypeAryPtr *DOUBLES;
static const TypeAryPtr* BOTTOM;
static const TypeAryPtr* RANGE;
static const TypeAryPtr* OOPS;
static const TypeAryPtr* NARROWOOPS;
static const TypeAryPtr* BYTES;
static const TypeAryPtr* SHORTS;
static const TypeAryPtr* CHARS;
static const TypeAryPtr* INTS;
static const TypeAryPtr* LONGS;
static const TypeAryPtr* FLOATS;
static const TypeAryPtr* DOUBLES;
// selects one of the above:
static const TypeAryPtr *get_array_body_type(BasicType elem) {
assert((uint)elem <= T_CONFLICT && _array_body_type[elem] != nullptr, "bad elem type");

View File

@@ -1637,8 +1637,9 @@ bool LibraryCallKit::inline_vector_reduction() {
int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt);
int sopc = ReductionNode::opcode(opc, elem_bt);
// Ensure reduction operation for lanewise operation
// When using mask, mask use type needs to be VecMaskUseLoad.
if (!arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) {
if (sopc == opc || !arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) {
log_if_needed(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=%d",
sopc, num_elem, type2name(elem_bt), is_masked_op ? 1 : 0);
return false;

View File

@@ -1466,6 +1466,9 @@ bool VectorCastNode::implemented(int opc, uint vlen, BasicType src_type, BasicTy
if (is_java_primitive(dst_type) &&
is_java_primitive(src_type) &&
(vlen > 1) && is_power_of_2(vlen) &&
// In rare case, the input to the VectorCast could be a Replicate node. We need to make sure creating is supported:
// check the src_type:
VectorNode::vector_size_supported_auto_vectorization(src_type, vlen) &&
VectorNode::vector_size_supported_auto_vectorization(dst_type, vlen)) {
int vopc = VectorCastNode::opcode(opc, src_type);
return vopc > 0 && Matcher::match_rule_supported_auto_vectorization(vopc, vlen, dst_type);

View File

@@ -598,7 +598,7 @@ JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) {
}
// compute interp_only mode
bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0 || has_frame_pops;
bool is_now_interp = state->is_interp_only_mode();
bool is_now_interp = state->is_interp_only_mode() || state->is_pending_interp_only_mode();
if (should_be_interp != is_now_interp) {
if (should_be_interp) {

View File

@@ -60,14 +60,14 @@ JVM_END
#if INCLUDE_JVMTI
class JvmtiUnmountBeginMark : public StackObj {
Handle _vthread;
JavaThread* _target;
JavaThread* _current;
freeze_result _result;
bool _failed;
public:
JvmtiUnmountBeginMark(JavaThread* t) :
_vthread(t, t->vthread()), _target(t), _result(freeze_pinned_native), _failed(false) {
assert(!_target->is_in_VTMS_transition(), "must be");
_vthread(t, t->vthread()), _current(t), _result(freeze_pinned_native), _failed(false) {
assert(!_current->is_in_VTMS_transition(), "must be");
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount((jthread)_vthread.raw_value(), true);
@@ -75,26 +75,26 @@ class JvmtiUnmountBeginMark : public StackObj {
// Don't preempt if there is a pending popframe or earlyret operation. This can
// be installed in start_VTMS_transition() so we need to check it here.
if (JvmtiExport::can_pop_frame() || JvmtiExport::can_force_early_return()) {
JvmtiThreadState* state = _target->jvmti_thread_state();
if (_target->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) {
JvmtiThreadState* state = _current->jvmti_thread_state();
if (_current->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) {
_failed = true;
}
}
// Don't preempt in case there is an async exception installed since
// we would incorrectly throw it during the unmount logic in the carrier.
if (_target->has_async_exception_condition()) {
if (_current->has_async_exception_condition()) {
_failed = true;
}
} else {
_target->set_is_in_VTMS_transition(true);
_current->set_is_in_VTMS_transition(true);
java_lang_Thread::set_is_in_VTMS_transition(_vthread(), true);
}
}
~JvmtiUnmountBeginMark() {
assert(!_target->is_suspended(), "must be");
assert(!_current->is_suspended(), "must be");
assert(_target->is_in_VTMS_transition(), "must be");
assert(_current->is_in_VTMS_transition(), "must be");
assert(java_lang_Thread::is_in_VTMS_transition(_vthread()), "must be");
// Read it again since for late binding agents the flag could have
@@ -106,7 +106,7 @@ class JvmtiUnmountBeginMark : public StackObj {
if (jvmti_present) {
JvmtiVTMSTransitionDisabler::VTMS_vthread_mount((jthread)_vthread.raw_value(), false);
} else {
_target->set_is_in_VTMS_transition(false);
_current->set_is_in_VTMS_transition(false);
java_lang_Thread::set_is_in_VTMS_transition(_vthread(), false);
}
}
@@ -115,51 +115,59 @@ class JvmtiUnmountBeginMark : public StackObj {
bool failed() { return _failed; }
};
static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* target) {
if (target->is_in_VTMS_transition()) {
// We caught target at the end of a mount transition.
static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* current) {
if (current->is_in_VTMS_transition()) {
// We are at the end of a mount transition.
return false;
}
return true;
}
#endif // INCLUDE_JVMTI
static bool is_vthread_safe_to_preempt(JavaThread* target, oop vthread) {
static bool is_vthread_safe_to_preempt(JavaThread* current, oop vthread) {
assert(java_lang_VirtualThread::is_instance(vthread), "");
if (java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition
return false;
}
return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(target)) NOT_JVMTI(true);
return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(current)) NOT_JVMTI(true);
}
typedef freeze_result (*FreezeContFnT)(JavaThread*, intptr_t*);
static void verify_preempt_preconditions(JavaThread* target, oop continuation) {
assert(target == JavaThread::current(), "no support for external preemption");
assert(target->has_last_Java_frame(), "");
assert(!target->preempting(), "");
assert(target->last_continuation() != nullptr, "");
assert(target->last_continuation()->cont_oop(target) == continuation, "");
static void verify_preempt_preconditions(JavaThread* current, oop continuation) {
assert(current == JavaThread::current(), "no support for external preemption");
assert(current->has_last_Java_frame(), "");
assert(!current->preempting(), "");
assert(current->last_continuation() != nullptr, "");
assert(current->last_continuation()->cont_oop(current) == continuation, "");
assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), "");
assert(!target->has_pending_exception(), "");
assert(!current->has_pending_exception(), "");
}
freeze_result Continuation::try_preempt(JavaThread* target, oop continuation) {
verify_preempt_preconditions(target, continuation);
freeze_result Continuation::try_preempt(JavaThread* current, oop continuation) {
verify_preempt_preconditions(current, continuation);
if (LockingMode == LM_LEGACY) {
return freeze_unsupported;
}
if (!is_vthread_safe_to_preempt(target, target->vthread())) {
if (!is_vthread_safe_to_preempt(current, current->vthread())) {
return freeze_pinned_native;
}
JVMTI_ONLY(JvmtiUnmountBeginMark jubm(target);)
JVMTI_ONLY(JvmtiUnmountBeginMark jubm(current);)
JVMTI_ONLY(if (jubm.failed()) return freeze_pinned_native;)
freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp());
freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(current, current->last_Java_sp());
log_trace(continuations, preempt)("try_preempt: %d", res);
JVMTI_ONLY(jubm.set_result(res);)
if (current->has_pending_exception()) {
assert(res == freeze_exception, "expecting an exception result from freeze");
// We don't want to throw exceptions, especially when returning
// from monitorenter since the compiler does not expect one. We
// just ignore the exception and pin the vthread to the carrier.
current->clear_pending_exception();
}
return res;
}

View File

@@ -2603,6 +2603,7 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n
|| (stub_caller && f.cb()->as_nmethod()->is_marked_for_deoptimization())) {
// The caller of the safepoint stub when the continuation is preempted is not at a call instruction, and so
// cannot rely on nmethod patching for deopt.
assert(_thread->is_interp_only_mode() || stub_caller, "expected a stub-caller");
log_develop_trace(continuations)("Deoptimizing thawed frame");
DEBUG_ONLY(ContinuationHelper::Frame::patch_pc(f, nullptr));

View File

@@ -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;

View File

@@ -2349,11 +2349,10 @@ void VM_HeapDumper::dump_threads(AbstractDumpWriter* writer) {
}
bool VM_HeapDumper::doit_prologue() {
if (_gc_before_heap_dump && UseZGC) {
// ZGC cannot perform a synchronous GC cycle from within the VM thread.
// So ZCollectedHeap::collect_as_vm_thread() is a noop. To respect the
// _gc_before_heap_dump flag a synchronous GC cycle is performed from
// the caller thread in the prologue.
if (_gc_before_heap_dump && (UseZGC || UseShenandoahGC)) {
// ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread.
// So collect_as_vm_thread() is a noop. To respect the _gc_before_heap_dump flag a
// synchronous GC cycle is performed from the caller thread in the prologue.
Universe::heap()->collect(GCCause::_heap_dump);
}
return VM_GC_Operation::doit_prologue();

View File

@@ -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
@@ -180,8 +180,8 @@ abstract class HKDFKeyDerivation extends KDFSpi {
} else if (derivationSpec instanceof HKDFParameterSpec.Expand anExpand) {
// set this value in the "if"
if ((pseudoRandomKey = anExpand.prk().getEncoded()) == null) {
throw new AssertionError(
"PRK is required for HKDFParameterSpec.Expand");
throw new InvalidAlgorithmParameterException(
"Cannot retrieve PRK for HKDFParameterSpec.Expand");
}
// set this value in the "if"
if ((info = anExpand.info()) == null) {
@@ -411,4 +411,4 @@ abstract class HKDFKeyDerivation extends KDFSpi {
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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
@@ -349,8 +349,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* @jls 15.21.1 Numerical Equality Operators == and !=
* @jls 15.20.1 Numerical Comparison Operators {@code <}, {@code <=}, {@code >}, and {@code >=}
*
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
* @spec https://standards.ieee.org/ieee/754/6210/
* IEEE Standard for Floating-Point Arithmetic
*
* @author Lee Boynton
* @author Arthur van Hoff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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
@@ -67,8 +67,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* decimal conversion issues} in {@code java.lang.Double} is also
* applicable to {@code float} values.
*
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
* @spec https://standards.ieee.org/ieee/754/6210/
* IEEE Standard for Floating-Point Arithmetic
*
* @author Lee Boynton
* @author Arthur van Hoff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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
@@ -120,8 +120,8 @@ import static java.lang.Double.*;
* implementation condition than required for most of the methods in
* question that are also included in this class.
*
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
* @spec https://standards.ieee.org/ieee/754/6210/
* IEEE Standard for Floating-Point Arithmetic
*
* @since 1.0
*/

View File

@@ -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
@@ -98,8 +98,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* href="Math.html#Ieee754RecommendedOps">relate to the IEEE 754
* recommended operations</a>.
*
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
* @spec https://standards.ieee.org/ieee/754/6210/
* IEEE Standard for Floating-Point Arithmetic
*
* @author Joseph D. Darcy
* @since 1.3

View File

@@ -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,33 @@ import java.util.Set;
import jdk.internal.classfile.impl.AccessFlagsImpl;
/**
* Models the access flags for a class, method, or field. Delivered as a
* {@link ClassElement}, {@link FieldElement}, or {@link MethodElement}
* when traversing the corresponding model type.
* Models the access flags for a class, method, or field. The access flags
* appears exactly once in each class, method, or field; a {@link
* ClassBuilder} and a {@link FieldBuilder} chooses an unspecified default value
* if access flags are not provided, and a {@link MethodBuilder} is always
* created with access flags.
* <p>
* {@code AccessFlags} cannot be created via a factory method directly; it can
* be created with {@code withFlags} methods on the respective builders.
* <p>
* A {@link MethodBuilder} throws an {@link IllegalArgumentException} if it is
* supplied an {@code AccessFlags} object that changes the preexisting
* {@link ClassFile#ACC_STATIC ACC_STATIC} flag of the builder, because the
* access flag change may invalidate previously supplied data to the builder.
*
* @apiNote
* The access flags of classes, methods, and fields are modeled as a standalone
* object to support streaming as elements for {@link ClassFileTransform}.
* Other access flags are not elements of a {@link CompoundElement} and thus not
* modeled by {@code AccessFlags}; they provide their own {@code flagsMask},
* {@code flags}, and {@code has} methods.
*
* @see ClassModel#flags()
* @see FieldModel#flags()
* @see MethodModel#flags()
* @see ClassBuilder#withFlags
* @see FieldBuilder#withFlags
* @see MethodBuilder#withFlags
* @since 24
*/
public sealed interface AccessFlags
@@ -41,26 +64,36 @@ public sealed interface AccessFlags
permits AccessFlagsImpl {
/**
* {@return the access flags, as a bit mask}
* {@return the access flags, as a bit mask} It is in the range of unsigned
* short, {@code [0, 0xFFFF]}.
*/
int flagsMask();
/**
* {@return the access flags}
* {@return the access flags, as a set of flag enums}
*
* @throws IllegalArgumentException if the flags mask has any undefined bit set
* @see #location()
*/
Set<AccessFlag> flags();
/**
* {@return whether the specified flag is present} The specified flag
* should be a valid flag for the classfile location associated with this
* element otherwise false is returned.
* {@return whether the specified flag is set} If the specified flag
* is not available to this {@linkplain #location() location}, returns
* {@code false}.
*
* @param flag the flag to test
* @see #location()
*/
boolean has(AccessFlag flag);
/**
* {@return the classfile location for this element, which is either class,
* method, or field}
* {@return the {@code class} file location for this element, which is
* either class, method, or field}
*
* @see AccessFlag.Location#CLASS
* @see AccessFlag.Location#FIELD
* @see AccessFlag.Location#METHOD
*/
AccessFlag.Location location();
}

View File

@@ -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,8 +41,9 @@ import jdk.internal.classfile.impl.Util;
* type_annotation} structure (JVMS {@jvms 4.7.20}). This model indicates the
* interface of the annotation and a set of element-value pairs.
* <p>
* This model can reconstruct an annotation, given the location of the modeled structure
* in the class file and the definition of the annotation interface.
* This model can reconstruct an annotation, given the location of the modeled
* structure in the {@code class} file and the definition of the annotation
* interface.
* <p>
* Two {@code Annotation} objects should be compared using the {@link
* Object#equals(Object) equals} method.
@@ -54,8 +55,8 @@ import jdk.internal.classfile.impl.Util;
* elements with default values (JLS {@jls 9.6.2}), and whether the reconstructed annotation
* is a container annotation for multiple annotations (JLS {@jls 9.7.5}).
*
* @see AnnotationElement
* @see AnnotationValue
* @see java.lang.annotation.Annotation
* @see java.lang.reflect.AnnotatedElement Annotations in core reflection
* @see TypeAnnotation
* @see RuntimeVisibleAnnotationsAttribute
* @see RuntimeInvisibleAnnotationsAttribute
@@ -70,11 +71,15 @@ public sealed interface Annotation
/**
* {@return the constant pool entry holding the {@linkplain Class#descriptorString
* descriptor string} of the annotation interface}
*
* @see java.lang.annotation.Annotation#annotationType()
*/
Utf8Entry className();
/**
* {@return the annotation interface, as a symbolic descriptor}
*
* @see java.lang.annotation.Annotation#annotationType()
*/
default ClassDesc classSymbol() {
return Util.fieldTypeSymbol(className());

View File

@@ -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
@@ -40,8 +40,8 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
* {@link Object#equals(Object) equals} method.
*
* @see Annotation
* @see AnnotationValue
*
* @see java.lang.reflect.AnnotatedElement Annotations in core reflection
* @jvms 4.7.16.1 The {@code element_value} structure
* @since 24
*/
public sealed interface AnnotationElement

View File

@@ -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
@@ -45,6 +45,7 @@ import static java.util.Objects.requireNonNull;
*
* @see Annotation
* @see AnnotationElement
* @see java.lang.reflect.AnnotatedElement Annotations in core reflection
*
* @sealedGraph
* @since 24
@@ -53,7 +54,7 @@ public sealed interface AnnotationValue {
/**
* Models an annotation value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ANNOTATION}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ANNOTATION}.
*
* @since 24
*/
@@ -65,7 +66,7 @@ public sealed interface AnnotationValue {
/**
* Models an array value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ARRAY}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ARRAY}.
*
* @since 24
*/
@@ -121,7 +122,7 @@ public sealed interface AnnotationValue {
/**
* Models a string value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_STRING}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_STRING}.
*
* @since 24
*/
@@ -148,7 +149,7 @@ public sealed interface AnnotationValue {
/**
* Models a double value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_DOUBLE}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_DOUBLE}.
*
* @since 24
*/
@@ -175,7 +176,7 @@ public sealed interface AnnotationValue {
/**
* Models a float value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_FLOAT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_FLOAT}.
*
* @since 24
*/
@@ -202,7 +203,7 @@ public sealed interface AnnotationValue {
/**
* Models a long value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_LONG}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_LONG}.
*
* @since 24
*/
@@ -229,7 +230,7 @@ public sealed interface AnnotationValue {
/**
* Models an int value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_INT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_INT}.
*
* @since 24
*/
@@ -256,7 +257,7 @@ public sealed interface AnnotationValue {
/**
* Models a short value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_SHORT}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_SHORT}.
*
* @since 24
*/
@@ -286,7 +287,7 @@ public sealed interface AnnotationValue {
/**
* Models a char value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_CHAR}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_CHAR}.
*
* @since 24
*/
@@ -316,7 +317,7 @@ public sealed interface AnnotationValue {
/**
* Models a byte value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_BYTE}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_BYTE}.
*
* @since 24
*/
@@ -346,7 +347,7 @@ public sealed interface AnnotationValue {
/**
* Models a boolean value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_BOOLEAN}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_BOOLEAN}.
*
* @since 24
*/
@@ -376,7 +377,7 @@ public sealed interface AnnotationValue {
/**
* Models a class value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_CLASS}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_CLASS}.
*
* @since 24
*/
@@ -393,7 +394,7 @@ public sealed interface AnnotationValue {
/**
* Models an enum value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value TAG_ENUM}.
* The {@linkplain #tag tag} of this value is {@value %c TAG_ENUM}.
*
* @since 24
*/

View File

@@ -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
@@ -31,15 +31,31 @@ import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a classfile attribute (JVMS {@jvms 4.7}). Many, though not all, subtypes of
* {@linkplain Attribute} will implement {@link ClassElement}, {@link
* MethodElement}, {@link FieldElement}, or {@link CodeElement}; attributes that
* are also elements will be delivered when traversing the elements of the
* corresponding model type. Additionally, all attributes are accessible
* directly from the corresponding model type through {@link
* AttributedElement#findAttribute(AttributeMapper)}.
* @param <A> the attribute type
* Models an attribute (JVMS {@jvms 4.7}) in the {@code class} file format.
* Attributes exist on certain {@code class} file structures modeled by {@link
* AttributedElement}, which provides basic read access to the attributes.
* <p>
* This sealed interface hierarchy includes attributes predefined in the JVMS
* and JDK-specific nonstandard attributes. Their {@linkplain #attributeMapper()
* mappers} are available in {@link Attributes}. Two special subtypes of {@code
* Attribute} are {@link CustomAttribute}, which all user-defined attributes
* should extend from, and {@link UnknownAttribute}, representing attributes
* read from {@code class} file but are not recognized by the {@link
* ClassFile.AttributeMapperOption}.
* <p>
* Attributes are read through {@link AttributedElement} or element traversal of
* a {@link CompoundElement}; they are written through {@link ClassFileBuilder}.
* See {@linkplain java.lang.classfile.attribute##reading Reading Attributes}
* and {@linkplain java.lang.classfile.attribute##writing Writing Attributes}
* for more details.
*
* @param <A> the attribute type
* @see java.lang.classfile.attribute
* @see AttributeMapper
* @see AttributedElement
* @see CustomAttribute
* @see UnknownAttribute
* @jvms 4.7 Attributes
* @sealedGraph
* @since 24
*/
@@ -62,7 +78,13 @@ public sealed interface Attribute<A extends Attribute<A>>
StackMapTableAttribute, SyntheticAttribute,
UnknownAttribute, BoundAttribute, UnboundAttribute, CustomAttribute {
/**
* {@return the name of the attribute}
* {@return the name of the attribute} The {@linkplain
* Utf8Entry#stringValue() string value} of the name is equivalent to the
* value of {@link AttributeMapper#name() attributeMapper().name()}.
* <p>
* If this attribute is read from a {@code class} file, this method returns
* the {@link Utf8Entry} indicating the attribute name in the {@code class}
* file.
*/
Utf8Entry attributeName();

View File

@@ -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,54 +24,118 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.UnknownAttribute;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry;
/**
* Bidirectional mapper between the classfile representation of an attribute and
* how that attribute is modeled in the API. The attribute mapper is used
* to parse the classfile representation into a model, and to write the model
* representation back to a classfile. For each standard attribute, there is a
* predefined attribute mapper defined in {@link Attributes}. For nonstandard
* attributes, clients can define their own {@linkplain AttributeMapper}.
* Classes that model nonstandard attributes should extend {@link
* CustomAttribute}.
* @param <A> the attribute type
* Bidirectional mapper between the {@code class} file representation of an
* attribute and its API model. The attribute mapper identifies an attribute
* by its {@linkplain Attribute#attributeName name}, and is used to parse the
* {@code class} file representation into a model, and to write the model
* representation back to a {@code class} file.
* <p>
* {@link Attributes} defines the mappers for predefined attributes in the JVMS
* and certain conventional attributes. For other attributes (JVMS {@jvms
* 4.7.1}), users can define their own {@code AttributeMapper}; classes that
* model those attributes should extend {@link CustomAttribute}. To read those
* attributes, user-defined {@code AttributeMapper}s must be registered to the
* {@link ClassFile.AttributeMapperOption}.
*
* @param <A> the attribute type
* @see Attributes
* @see ClassFile.AttributeMapperOption
* @see java.lang.classfile.attribute
* @since 24
*/
public interface AttributeMapper<A extends Attribute<A>> {
/**
* Attribute stability indicator
* Indicates the data dependency of the {@code class} file representation
* of an attribute. Whether an attribute can be bulk-copied by its binary
* representation to a new {@code class} file depends on if its data refers
* to other parts of its enclosing {@code class} file.
*
* @apiNote
* This dependency is called "stability" because it indicates the conditions
* for a {@code class} file attribute to be eligible for bulk-copying to
* another {@code class} file.
*
* @see AttributeMapper#stability()
* @since 24
*/
enum AttributeStability {
/**
* The attribute contains only pure data, such as timestamps, and can always be bulk-copied.
* The attribute contains only standalone data, and has no reference to
* other parts of its enclosing {@code class} file, besides the name of
* the attribute. Thus, its contents can always be bulk-copied to
* another {@code class} file.
* <p>
* For example, a bit mask is standalone data.
*/
STATELESS,
/**
* The attribute contains only pure data and CP refs, so can be bulk-copied when CP sharing is in effect,
* and need to be exploded and rewritten when CP sharing is not in effect.
* In addition to standalone data, the attribute refers to the constant
* pool, including the {@link BootstrapMethodsAttribute BootstrapMethods}
* attribute, of its enclosing {@code class} file. Thus, it can be
* bulk-copied when the destination {@code class} file extends its
* constant pool from that of the original {@code class}. It must be
* expanded to translate constant pool references and rewritten when
* constant pool indices are not compatible.
* <p>
* For example, a {@link Utf8Entry} is a reference to the constant pool.
*
* @see ConstantPoolBuilder#of(ClassModel)
* @see ClassFile.ConstantPoolSharingOption
*/
CP_REFS,
/**
* The attribute may contain labels, so need to be exploded and rewritten when the Code array is perturbed.
* In addition to standalone data and references to the constant pool,
* the attribute refers to positions into the {@code code} array of a
* {@link CodeAttribute Code} attribute. Thus, it can be bulked-copied
* when the {@code code} array is unchanged, which requires that the
* destination {@code class} file extends its constant pool from that of
* the original {@code class}. It must be expanded to translate {@link
* Label}s or constant pool references and rewritten if the {@code code}
* array is perturbed, including when constant pool indices are not
* compatible.
* <p>
* For example, a bci value, modeled by a {@link Label}, is a reference
* to a position in the {@code code} array.
*/
LABELS,
/**
* The attribute may contain indexes into structured not managed by the library (type variable lists, etc)
* and so we consult the {@link ClassFile.AttributesProcessingOption} option to determine whether to preserve
* or drop it during transformation.
* The attribute refers to structures not managed by the library (type
* variable lists, etc.). As a result, even when the attribute is
* expanded, those references may not be correctly translated, and the
* rewritten results may be incorrect.
* <p>
* If the attribute is read from a {@code class} file, {@link
* ClassFile.AttributesProcessingOption} determines whether to preserve
* or drop the attribute during transformation.
*
* @see ClassFile.AttributesProcessingOption#DROP_UNSTABLE_ATTRIBUTES
*/
UNSTABLE,
/**
* The attribute is completely unknown and so we consult the {@link ClassFile.AttributesProcessingOption} option
* to determine whether to preserve or drop it during transformation.
* The attribute is completely unknown. As a result, expanding and
* rewriting is not possible, and any difference between the destination
* {@code class} file and its enclosing {@code class} file may make the
* attribute incorrect.
* <p>
* {@link ClassFile.AttributesProcessingOption} determines whether to
* preserve or drop the attribute during transformation.
*
* @see UnknownAttribute
* @see ClassFile.AttributesProcessingOption#DROP_UNSTABLE_ATTRIBUTES
* @see ClassFile.AttributesProcessingOption#DROP_UNKNOWN_ATTRIBUTES
*/
UNKNOWN
}
@@ -82,35 +146,104 @@ public interface AttributeMapper<A extends Attribute<A>> {
String name();
/**
* Create an {@link Attribute} instance from a classfile.
* Creates an {@link Attribute} instance from a {@code class} file for the
* Class-File API.
* <p>
* This method is called by the Class-File API to support reading of
* attributes. Users should never call this method.
* <p>
* The Class-File API makes these promises about the call to this method:
* <ul>
* <li>The {@link Utf8Entry} for the name of the attribute is accessible
* with {@code cf.readEntry(pos - 6, Utf8Entry.class)}, and is validated;
* <li>The length of the attribute is accessible with {@code cf.readInt(pos
* - 4)}, and is validated to be positive and not beyond the length of the
* {@code class} file;
* <li>The {@link AttributedElement} attribute access functionalities on the
* {@code enclosing} model may not be accessed when this method is called,
* but can be accessed later by the returned attribute when it is accessible
* to users.
* </ul>
* <p>
* The returned {@code Attribute} must fulfill these requirements:
* <ul>
* <li>{@link Attribute#attributeMapper()} returns this mapper;
* <li>{@link Attribute#attributeName()} returns the attribute name in the
* {@code class} file.
* </ul>
*
* @param enclosing The class, method, field, or code attribute in which
* this attribute appears
* @param cf The {@link ClassReader} describing the classfile to read from
* @param pos The offset into the classfile at which the attribute starts
* @return the new attribute
* @apiNote
* Implementations of this method should perform minimal work to return an
* attribute, as this method is called even if the resulting attribute is
* never used. In particular, the implementation should avoid checking the
* validity of the attribute {@code class} file data or performing actions
* that may throw exceptions.
*
* @param enclosing the structure in which this attribute appears
* @param cf provides access to the {@code class} file to read from
* @param pos the offset into the {@code class} file at which the contents
* of the attribute starts
* @return the read attribute
*/
A readAttribute(AttributedElement enclosing, ClassReader cf, int pos);
/**
* Write an {@link Attribute} instance to a classfile.
* Writes an {@link Attribute} instance to a {@code class} file for the
* Class-File API.
* <p>
* This method is called by the Class-File API to support writing of
* attributes. Users should never call this method.
* <p>
* The Class-File API makes these promises about the call to this method:
* <ul>
* <li>{@link Attribute#attributeMapper() attr.attributeMapper()} returns
* this mapper;
* <li>The {@code buf} may already have data written, that its {@link
* BufWriter#size() size} may not be {@code 0}.
* </ul>
* <p>
* The {@code class} file writing must fulfill these requirements:
* <ul>
* <li>The attribute name {@code u2} and attribute length {@code u4} must
* be written to the {@code buf};
* <li>{@link Attribute#attributeName() attr.attributeName()} is written as
* if with {@code buf.writeIndex(attr.attributeName())};
* <li>The attribute length is the length, in bytes, of attribute contents
* written to the {@code buf}, not including the 6 bytes used by the name
* and the length;
* <li>If any information in the API model of the attribute, {@code attr},
* cannot be represented in the {@code class} file format of the attribute,
* an {@link IllegalArgumentException} is thrown.
* </ul>
*
* @param buf The {@link BufWriter} to which the attribute should be written
* @param attr The attribute to write
* @apiNote
* {@link BufWriter#patchInt} can be used to update the attribute length
* after the attribute contents are written to the {@code buf}.
*
* @param buf the {@link BufWriter} to which the attribute should be written
* @param attr the attribute to write
* @throws IllegalArgumentException if some data in the API model of the
* attribute is invalid for the {@code class} file format
*/
void writeAttribute(BufWriter buf, A attr);
/**
* {@return whether this attribute may appear more than once in a given location}
* {@return whether this attribute may appear more than once in one
* structure}
* <p>
* If an attribute does not allow multiple instances in one structure,
* can be supplied to a {@link ClassFileBuilder}, and multiple instances of
* the attribute are supplied to the builder, the last supplied attribute
* appears on the built structure.
*
* @implSpec The default implementation returns {@code false}
* @implSpec The default implementation returns {@code false}.
*/
default boolean allowMultiple() {
return false;
}
/**
* {@return attribute stability indicator}
* {@return the data dependency of this attribute on the {@code class} file}
*/
AttributeStability stability();
}

View File

@@ -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,6 +24,7 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.RecordComponentInfo;
import java.util.ArrayList;
import java.util.Collections;
@@ -35,9 +36,18 @@ import jdk.internal.classfile.impl.AbstractUnboundModel;
import static java.util.Objects.requireNonNull;
/**
* A {@link ClassFileElement} describing an entity that has attributes, such
* as a class, field, method, code attribute, or record component.
* A {@link ClassFileElement} describing a {@code class} file structure that has
* attributes, such as a {@code class} file, a field, a method, a {@link
* CodeAttribute Code} attribute, or a record component.
* <p>
* Unless otherwise specified, most attributes that can be discovered in a
* {@link CompoundElement} implements the corresponding {@linkplain
* ClassFileElement##membership membership subinterface} of {@code
* ClassFileElement}, and can be sent to a {@link ClassFileBuilder} to be
* integrated into the built structure.
*
* @see java.lang.classfile.attribute
* @jvms 4.7 Attributes
* @sealedGraph
* @since 24
*/
@@ -46,15 +56,28 @@ public sealed interface AttributedElement extends ClassFileElement
RecordComponentInfo, AbstractUnboundModel {
/**
* {@return the attributes of this element}
* {@return the attributes of this structure}
*/
List<Attribute<?>> attributes();
/**
* Finds an attribute by name.
* Finds an attribute by name. This is suitable to find attributes that
* {@linkplain AttributeMapper#allowMultiple() allow at most one instance}
* in one structure. If this is used to find attributes that allow multiple
* instances in one structure, the first matching instance is returned.
*
* @apiNote
* This can easily find an attribute and send it to another {@link
* ClassFileBuilder}, which is a {@code Consumer}:
* {@snippet lang=java :
* MethodModel method = null; // @replace substring=null; replacement=...
* MethodBuilder mb = null; // @replace substring=null; replacement=...
* method.findAttribute(Attributes.code()).ifPresent(mb);
* }
*
* @param attr the attribute mapper
* @param <T> the type of the attribute
* @return the attribute, or an empty {@linkplain Optional} if the attribute
* @return the attribute, or {@code Optional.empty()} if the attribute
* is not present
*/
default <T extends Attribute<T>> Optional<T> findAttribute(AttributeMapper<T> attr) {
@@ -70,10 +93,13 @@ public sealed interface AttributedElement extends ClassFileElement
}
/**
* Finds one or more attributes by name.
* Finds attributes by name. This is suitable to find attributes that
* {@linkplain AttributeMapper#allowMultiple() allow multiple instances}
* in one structure.
*
* @param attr the attribute mapper
* @param <T> the type of the attribute
* @return the attributes, or an empty {@linkplain List} if the attribute
* @return the attributes, or an empty {@code List} if the attribute
* is not present
*/
default <T extends Attribute<T>> List<T> findAttributes(AttributeMapper<T> attr) {

View File

@@ -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,64 +30,20 @@ import java.lang.classfile.attribute.*;
import jdk.internal.classfile.impl.AbstractAttributeMapper.*;
/**
* Attribute mappers for standard classfile attributes.
* Attribute mappers for predefined (JVMS {@jvms 4.7}) and JDK-specific
* nonstandard attributes.
* <p>
* Unless otherwise specified, mappers returned by each method
* do not permit multiple attribute instances in a given location.
* <p>
* The most stable {@link AttributeStability#STATELESS STATELESS} mappers are:
* Unless otherwise specified, each mapper returned by methods in this class:
* <ul>
* <li>{@link #deprecated()}
* <li>{@link #moduleResolution()}
* <li>{@link #sourceDebugExtension()}
* <li>{@link #synthetic()}
* </ul>
*
* The mappers with {@link AttributeStability#CP_REFS CP_REFS} stability are:
* <ul>
* <li>{@link #annotationDefault()}
* <li>{@link #bootstrapMethods()}
* <li>{@link #code()}
* <li>{@link #compilationId()}
* <li>{@link #constantValue()}
* <li>{@link #enclosingMethod()}
* <li>{@link #exceptions()}
* <li>{@link #innerClasses()}
* <li>{@link #methodParameters()}
* <li>{@link #module()}
* <li>{@link #moduleHashes()}
* <li>{@link #moduleMainClass()}
* <li>{@link #modulePackages()}
* <li>{@link #moduleTarget()}
* <li>{@link #nestHost()}
* <li>{@link #nestMembers()}
* <li>{@link #permittedSubclasses()}
* <li>{@link #record()}
* <li>{@link #runtimeInvisibleAnnotations()}
* <li>{@link #runtimeInvisibleParameterAnnotations()}
* <li>{@link #runtimeVisibleAnnotations()}
* <li>{@link #runtimeVisibleParameterAnnotations()}
* <li>{@link #signature()}
* <li>{@link #sourceFile()}
* <li>{@link #sourceId()}
* </ul>
*
* The mappers with {@link AttributeStability#LABELS LABELS} stability are:
* <ul>
* <li>{@link #characterRangeTable()}
* <li>{@link #lineNumberTable()}
* <li>{@link #localVariableTable()}
* <li>{@link #localVariableTypeTable()}
* </ul>
*
* The {@link AttributeStability#UNSTABLE UNSTABLE} mappers are:
* <ul>
* <li>{@link #runtimeInvisibleTypeAnnotations()}
* <li>{@link #runtimeVisibleTypeAnnotations()}
* <li>is predefined in the JVMS instead of JDK-specific;
* <li>does not permit {@linkplain AttributeMapper#allowMultiple() multiple
* attribute instances} in the same structure;
* <li>the attribute has a {@linkplain AttributeMapper#stability() data
* dependency} on the {@linkplain AttributeStability#CP_REFS constant pool}.
* </ul>
*
* @see AttributeMapper
*
* @see java.lang.classfile.attribute
* @since 24
*/
public final class Attributes {
@@ -204,258 +160,278 @@ public final class Attributes {
}
/**
* {@return Attribute mapper for the {@code AnnotationDefault} attribute}
* {@return the mapper for the {@code AnnotationDefault} attribute}
*/
public static AttributeMapper<AnnotationDefaultAttribute> annotationDefault() {
return AnnotationDefaultMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code BootstrapMethods} attribute}
* {@return the mapper for the {@code BootstrapMethods} attribute}
*/
public static AttributeMapper<BootstrapMethodsAttribute> bootstrapMethods() {
return BootstrapMethodsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code CharacterRangeTable} attribute}
* The mapper permits multiple instances in a given location.
* {@return the mapper for the {@code CharacterRangeTable} attribute}
* This is a JDK-specific attribute.
* The mapper permits multiple instances in a {@code Code} attribute, but this
* attribute should be only emitted once.
* This has a data dependency on {@linkplain AttributeStability#LABELS labels}.
*/
public static AttributeMapper<CharacterRangeTableAttribute> characterRangeTable() {
return CharacterRangeTableMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Code} attribute}
* {@return the mapper for the {@code Code} attribute}
*/
public static AttributeMapper<CodeAttribute> code() {
return CodeMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code CompilationID} attribute}
* {@return the mapper for the {@code CompilationID} attribute}
* This is a JDK-specific attribute.
*/
public static AttributeMapper<CompilationIDAttribute> compilationId() {
return CompilationIDMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ConstantValue} attribute}
* {@return the mapper for the {@code ConstantValue} attribute}
*/
public static AttributeMapper<ConstantValueAttribute> constantValue() {
return ConstantValueMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Deprecated} attribute}
* {@return the mapper for the {@code Deprecated} attribute}
* The mapper permits multiple instances in a given location.
* This has {@linkplain AttributeStability#STATELESS no data dependency}.
*/
public static AttributeMapper<DeprecatedAttribute> deprecated() {
return DeprecatedMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code EnclosingMethod} attribute}
* {@return the mapper for the {@code EnclosingMethod} attribute}
*/
public static AttributeMapper<EnclosingMethodAttribute> enclosingMethod() {
return EnclosingMethodMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Exceptions} attribute}
* {@return the mapper for the {@code Exceptions} attribute}
*/
public static AttributeMapper<ExceptionsAttribute> exceptions() {
return ExceptionsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code InnerClasses} attribute}
* {@return the mapper for the {@code InnerClasses} attribute}
*/
public static AttributeMapper<InnerClassesAttribute> innerClasses() {
return InnerClassesMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code LineNumberTable} attribute}
* The mapper permits multiple instances in a given location.
* {@return the mapper for the {@code LineNumberTable} attribute}
* The mapper permits multiple instances in a {@code Code} attribute.
* This has a data dependency on {@linkplain AttributeStability#LABELS labels}.
*/
public static AttributeMapper<LineNumberTableAttribute> lineNumberTable() {
return LineNumberTableMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code LocalVariableTable} attribute}
* The mapper permits multiple instances in a given location.
* {@return the mapper for the {@code LocalVariableTable} attribute}
* The mapper permits multiple instances in a {@code Code} attribute.
* This has a data dependency on {@linkplain AttributeStability#LABELS labels}.
*/
public static AttributeMapper<LocalVariableTableAttribute> localVariableTable() {
return LocalVariableTableMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code LocalVariableTypeTable} attribute}
* {@return the mapper for the {@code LocalVariableTypeTable} attribute}
* The mapper permits multiple instances in a given location.
* This has a data dependency on {@linkplain AttributeStability#LABELS labels}.
*/
public static AttributeMapper<LocalVariableTypeTableAttribute> localVariableTypeTable() {
return LocalVariableTypeTableMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code MethodParameters} attribute}
* {@return the mapper for the {@code MethodParameters} attribute}
*/
public static AttributeMapper<MethodParametersAttribute> methodParameters() {
return MethodParametersMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Module} attribute}
* {@return the mapper for the {@code Module} attribute}
*/
public static AttributeMapper<ModuleAttribute> module() {
return ModuleMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ModuleHashes} attribute}
* {@return the mapper for the {@code ModuleHashes} attribute}
* This is a JDK-specific attribute.
*/
public static AttributeMapper<ModuleHashesAttribute> moduleHashes() {
return ModuleHashesMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ModuleMainClass} attribute}
* {@return the mapper for the {@code ModuleMainClass} attribute}
*/
public static AttributeMapper<ModuleMainClassAttribute> moduleMainClass() {
return ModuleMainClassMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ModulePackages} attribute}
* {@return the mapper for the {@code ModulePackages} attribute}
*/
public static AttributeMapper<ModulePackagesAttribute> modulePackages() {
return ModulePackagesMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ModuleResolution} attribute}
* {@return the mapper for the {@code ModuleResolution} attribute}
* This is a JDK-specific attribute.
* This has {@linkplain AttributeStability#STATELESS no data dependency}.
*/
public static AttributeMapper<ModuleResolutionAttribute> moduleResolution() {
return ModuleResolutionMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code ModuleTarget} attribute}
* {@return the mapper for the {@code ModuleTarget} attribute}
* This is a JDK-specific attribute.
*/
public static AttributeMapper<ModuleTargetAttribute> moduleTarget() {
return ModuleTargetMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code NestHost} attribute}
* {@return the mapper for the {@code NestHost} attribute}
*/
public static AttributeMapper<NestHostAttribute> nestHost() {
return NestHostMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code NestMembers} attribute}
* {@return the mapper for the {@code NestMembers} attribute}
*/
public static AttributeMapper<NestMembersAttribute> nestMembers() {
return NestMembersMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code PermittedSubclasses} attribute}
* {@return the mapper for the {@code PermittedSubclasses} attribute}
*/
public static AttributeMapper<PermittedSubclassesAttribute> permittedSubclasses() {
return PermittedSubclassesMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Record} attribute}
* {@return the mapper for the {@code Record} attribute}
*/
public static AttributeMapper<RecordAttribute> record() {
return RecordMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute}
* {@return the mapper for the {@code RuntimeInvisibleAnnotations} attribute}
*/
public static AttributeMapper<RuntimeInvisibleAnnotationsAttribute> runtimeInvisibleAnnotations() {
return RuntimeInvisibleAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute}
* {@return the mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute}
*/
public static AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> runtimeInvisibleParameterAnnotations() {
return RuntimeInvisibleParameterAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute}
* {@return the mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute}
* This has a data dependency on {@linkplain AttributeStability#UNSTABLE
* arbitrary indices} in the {@code class} file format.
*/
public static AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> runtimeInvisibleTypeAnnotations() {
return RuntimeInvisibleTypeAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute}
* {@return the mapper for the {@code RuntimeVisibleAnnotations} attribute}
*/
public static AttributeMapper<RuntimeVisibleAnnotationsAttribute> runtimeVisibleAnnotations() {
return RuntimeVisibleAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute}
* {@return the mapper for the {@code RuntimeVisibleParameterAnnotations} attribute}
*/
public static AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> runtimeVisibleParameterAnnotations() {
return RuntimeVisibleParameterAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute}
* {@return the mapper for the {@code RuntimeVisibleTypeAnnotations} attribute}
* This has a data dependency on {@linkplain AttributeStability#UNSTABLE
* arbitrary indices} in the {@code class} file format.
*/
public static AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> runtimeVisibleTypeAnnotations() {
return RuntimeVisibleTypeAnnotationsMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Signature} attribute}
* {@return the mapper for the {@code Signature} attribute}
*/
public static AttributeMapper<SignatureAttribute> signature() {
return SignatureMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code SourceDebugExtension} attribute}
* {@return the mapper for the {@code SourceDebugExtension} attribute}
* This has {@linkplain AttributeStability#STATELESS no data dependency}.
*/
public static AttributeMapper<SourceDebugExtensionAttribute> sourceDebugExtension() {
return SourceDebugExtensionMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code SourceFile} attribute}
* {@return the mapper for the {@code SourceFile} attribute}
*/
public static AttributeMapper<SourceFileAttribute> sourceFile() {
return SourceFileMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code SourceID} attribute}
* {@return the mapper for the {@code SourceID} attribute}
* This is a JDK-specific attribute.
*/
public static AttributeMapper<SourceIDAttribute> sourceId() {
return SourceIDMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code StackMapTable} attribute}
* {@return the mapper for the {@code StackMapTable} attribute}
* This has a data dependency on {@linkplain AttributeStability#LABELS labels}.
*/
public static AttributeMapper<StackMapTableAttribute> stackMapTable() {
return StackMapTableMapper.INSTANCE;
}
/**
* {@return Attribute mapper for the {@code Synthetic} attribute}
* {@return the mapper for the {@code Synthetic} attribute}
* The mapper permits multiple instances in a given location.
* This has {@linkplain AttributeStability#STATELESS no data dependency}.
*/
public static AttributeMapper<SyntheticAttribute> synthetic() {
return SyntheticMapper.INSTANCE;

View File

@@ -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 @@ import jdk.internal.classfile.impl.BootstrapMethodEntryImpl;
/**
* 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.
* <p>
* 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<LoadableConstantEntry> 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();

View File

@@ -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,120 +27,163 @@ package java.lang.classfile;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.PoolEntry;
import java.nio.ByteOrder;
import jdk.internal.classfile.impl.BufWriterImpl;
/**
* Supports writing portions of a classfile to a growable buffer. Methods
* are provided to write various standard entities (e.g., {@code u2}, {@code u4})
* to the end of the buffer, as well as to create constant pool entries.
* Advanced {@code class} file writing support for {@link AttributeMapper}s.
* Supports writing portions of a {@code class} file to a growable buffer, such
* as writing various numerical types (e.g., {@code u2}, {@code u4}), to the end
* of the buffer, as well as to create constant pool entries.
* <p>
* All numeric values in the {@code class} file format are {@linkplain
* ByteOrder#BIG_ENDIAN big endian}. Writing larger numeric values to smaller
* numeric values are always done with truncation, that the least significant
* bytes are kept and the other bytes are silently dropped. As a result,
* numeric value writing methods can write both signed and unsigned values, and
* users should validate their values before writing if silent dropping of most
* significant bytes is not the intended behavior.
*
* @see AttributeMapper#writeAttribute(BufWriter, Attribute)
* @since 24
*/
public sealed interface BufWriter
permits BufWriterImpl {
/** {@return the constant pool builder associated with this buffer} */
/**
* {@return the constant pool builder associated with this buffer}
*
* @see ClassFileBuilder#constantPool()
*/
ConstantPoolBuilder constantPool();
/**
* {@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 whether the provided constant pool is index-compatible with the
* constant pool of this buffer}
* <p>
* This is a shortcut for {@code constantPool().canWriteDirect(other)}.
*
* @param other the other constant pool
* @see ConstantPoolBuilder#canWriteDirect(ConstantPool)
*/
boolean canWriteDirect(ConstantPool other);
/**
* Ensure that the buffer has at least {@code freeBytes} bytes of unused space
* Ensures that the buffer has at least {@code freeBytes} bytes of free space
* in the end of the buffer.
* <p>
* The writing result is the same without calls to this method, but the
* writing process may be slower.
*
* @apiNote
* This is a hint that changes no visible state of the buffer; it helps to
* reduce reallocation of the underlying storage by allocating sufficient
* space at once.
*
* @param freeBytes the number of bytes to reserve
*/
void reserveSpace(int freeBytes);
/**
* Write an unsigned byte to the buffer
* Writes a byte to the buffer. {@code x} is truncated to a byte and
* written.
*
* @param x the byte value
* @param x the value to truncate to a byte
*/
void writeU1(int x);
/**
* Write an unsigned short to the buffer
* Writes 2 bytes, or a short, to the buffer. {@code x} is truncated to two
* bytes and written.
*
* @param x the short value
* @param x the value to truncate to a short
*/
void writeU2(int x);
/**
* Write a signed int to the buffer
* Writes 4 bytes, or an int, to the buffer.
*
* @param x the int value
*/
void writeInt(int x);
/**
* Write a float value to the buffer
* Writes a float value, of 4 bytes, to the buffer.
* <p>
* In the conversions, all NaN values of the {@code float} may or may not be
* collapsed into a single {@linkplain Float#NaN "canonical" NaN value}.
*
* @param x the float value
*/
void writeFloat(float x);
/**
* Write a long value to the buffer
* Writes 8 bytes, or a long, to the buffer.
*
* @param x the long value
*/
void writeLong(long x);
/**
* Write a double value to the buffer
* Writes a double value, of 8 bytes, to the buffer.
* <p>
* In the conversions, all NaN values of the {@code double} may or may not
* be collapsed into a single {@linkplain Double#NaN "canonical" NaN value}.
*
* @param x the int value
* @param x the double value
*/
void writeDouble(double x);
/**
* Write the contents of a byte array to the buffer
* Writes the contents of a byte array to the buffer.
*
* @param arr the byte array
*/
void writeBytes(byte[] arr);
/**
* Write a range of a byte array to the buffer
* Writes a range of a byte array to the buffer.
*
* @param arr the byte array
* @param start the offset within the byte array of the range
* @param start the start offset of the range within the byte array
* @param length the length of the range
* @throws IndexOutOfBoundsException if range is outside of the array bounds
* @throws IndexOutOfBoundsException if range is outside the array bounds
*/
void writeBytes(byte[] arr, int start, int length);
/**
* Patch a previously written integer value. Depending on the specified
* size, the entire value, or the low 1 or 2 bytes, may be written.
* Patches a previously written integer value. {@code value} is truncated
* to the given {@code size} number of bytes and written at the given {@code
* offset}. The end of this buffer stays unchanged.
*
* @param offset the offset at which to patch
* @apiNote
* The {@code offset} can be obtained by calling {@link #size()} before
* writing the previous integer value.
*
* @param offset the offset in this buffer at which to patch
* @param size the size of the integer value being written, in bytes
* @param value the integer value
* @param value the integer value to be truncated
* @throws IndexOutOfBoundsException if patched int is outside of bounds
* @see #size()
*/
void patchInt(int offset, int size, int value);
/**
* Write a 1, 2, 4, or 8 byte integer value to the buffer. Depending on
* the specified size, the entire value, or the low 1, 2, or 4 bytes, may
* be written.
* Writes a multibyte value to the buffer. {@code intValue} is truncated
* to the given {@code intSize} number of bytes and written.
*
* @param intSize the size of the integer value being written, in bytes
* @param intValue the integer value
* @param intValue the value to be truncated
*/
void writeIntBytes(int intSize, long intValue);
/**
* Write the index of the specified constant pool entry, as a {@code u2},
* to the buffer
* Writes the index of the specified constant pool entry as a {@link
* #writeU2 u2}. If the {@code entry} does not belong to the {@linkplain
* #constantPool() constant pool} of this buffer, it will be {@linkplain
* ConstantPoolBuilder##alien converted}, and the index of the converted
* pool entry is written instead.
*
* @param entry the constant pool entry
* @throws IllegalArgumentException if the entry has invalid index
@@ -148,16 +191,23 @@ public sealed interface BufWriter
void writeIndex(PoolEntry entry);
/**
* Write the index of the specified constant pool entry, as a {@code u2},
* to the buffer, or zero if the entry is null
* Writes the index of the specified constant pool entry, or the value
* {@code 0} if the specified entry is {@code null}, as a {@link #writeU2
* u2}. If the {@code entry} does not belong to the {@linkplain
* #constantPool() constant pool} of this buffer, it will be {@linkplain
* ConstantPoolBuilder##alien converted}, and the index of the converted
* pool entry is written instead.
*
* @param entry the constant pool entry
* @throws IllegalArgumentException if the entry has invalid index
* @param entry the constant pool entry, may be {@code null}
* @throws IllegalArgumentException if the entry is not {@code null} and has
* invalid index
*/
void writeIndexOrZero(PoolEntry entry);
/**
* {@return the number of bytes that have been written to the buffer}
*
* @see #patchInt(int, int, int)
*/
int size();
}

View File

@@ -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,8 +25,8 @@
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
@@ -41,14 +41,19 @@ import jdk.internal.classfile.impl.DirectClassBuilder;
import jdk.internal.classfile.impl.Util;
/**
* A builder for classfiles. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassFile#build(ClassDesc, Consumer)}
* or to class transforms. The elements of a classfile can be specified
* abstractly (by passing a {@link ClassElement} to {@link #with(ClassFileElement)})
* or concretely by calling the various {@code withXxx} methods.
* A builder for a {@code class} file. {@link ClassFile} provides different
* {@code build} methods that accept handlers to configure such a builder;
* {@link ClassFile#build(ClassDesc, Consumer)} suffices for basic usage, while
* {@link ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)} allows
* fine-grained control over {@linkplain ClassFileBuilder#constantPool() the
* constant pool}.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)
* @see ClassModel
* @see ClassTransform
*
* @since 24
*/
public sealed interface ClassBuilder
@@ -56,28 +61,38 @@ public sealed interface ClassBuilder
permits ChainedClassBuilder, DirectClassBuilder {
/**
* Sets the classfile version.
* Sets the version of this class.
*
* @param major the major version number
* @param minor the minor version number
* @return this builder
* @see ClassFileVersion
*/
default ClassBuilder withVersion(int major, int minor) {
return with(ClassFileVersion.of(major, minor));
}
/**
* Sets the classfile access flags.
* Sets the access flags of this class.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#CLASS
*/
default ClassBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.CLASS, flags));
}
/**
* Sets the classfile access flags.
* @param flags the access flags
* Sets the access flags of this class.
*
* @param flags the access flags, as flag enums
* @return this builder
* @throws IllegalArgumentException if any flag cannot be applied to the
* {@link AccessFlag.Location#CLASS} location
* @see AccessFlags
* @see AccessFlag.Location#CLASS
*/
default ClassBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.CLASS, flags));
@@ -85,8 +100,10 @@ public sealed interface ClassBuilder
/**
* Sets the superclass of this class.
*
* @param superclassEntry the superclass
* @return this builder
* @see Superclass
*/
default ClassBuilder withSuperclass(ClassEntry superclassEntry) {
return with(Superclass.of(superclassEntry));
@@ -94,9 +111,11 @@ public sealed interface ClassBuilder
/**
* Sets the superclass of this class.
*
* @param desc the superclass
* @return this builder
* @throws IllegalArgumentException if {@code desc} represents a primitive type
* @see Superclass
*/
default ClassBuilder withSuperclass(ClassDesc desc) {
return withSuperclass(constantPool().classEntry(desc));
@@ -104,8 +123,10 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @see Interfaces
*/
default ClassBuilder withInterfaces(List<ClassEntry> interfaces) {
return with(Interfaces.of(interfaces));
@@ -113,8 +134,10 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @see Interfaces
*/
default ClassBuilder withInterfaces(ClassEntry... interfaces) {
return withInterfaces(List.of(interfaces));
@@ -122,8 +145,11 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
* @see Interfaces
*/
default ClassBuilder withInterfaceSymbols(List<ClassDesc> interfaces) {
return withInterfaces(Util.entryList(interfaces));
@@ -131,32 +157,39 @@ public sealed interface ClassBuilder
/**
* Sets the interfaces of this class.
*
* @param interfaces the interfaces
* @return this builder
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
* @see Interfaces
*/
default ClassBuilder withInterfaceSymbols(ClassDesc... interfaces) {
// List view, since ref to interfaces is temporary
// list version does defensive copy
return withInterfaceSymbols(Arrays.asList(interfaces));
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
*
* @param name the field name
* @param descriptor the field descriptor string
* @param handler handler to supply the contents of the field
* @return this builder
* @see FieldModel
*/
ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
Consumer<? super FieldBuilder> handler);
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* Adds a field, with only access flags.
*
* @param name the field name
* @param descriptor the field descriptor string
* @param flags the access flags for this field, as a bit mask
* @return this builder
* @see FieldModel
* @see FieldBuilder#withFlags(int)
*/
default ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
@@ -166,11 +199,12 @@ public sealed interface ClassBuilder
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
*
* @param name the field name
* @param descriptor the symbolic field descriptor
* @param handler handler to supply the contents of the field
* @return this builder
* @see FieldModel
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
@@ -181,11 +215,14 @@ public sealed interface ClassBuilder
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* Adds a field, with only access flags.
*
* @param name the field name
* @param descriptor the symbolic field descriptor
* @param flags the access flags for this field, as a bit mask
* @return this builder
* @see FieldModel
* @see FieldBuilder#withFlags(int)
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
@@ -197,28 +234,33 @@ public sealed interface ClassBuilder
/**
* Adds a field by transforming a field from another class.
*
* @implNote
* <p>This method behaves as if:
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withField(field.fieldName(), field.fieldType(),
* b -> b.transformField(field, transform));
* // @link substring=withField target="#withField(Utf8Entry, Utf8Entry, Consumer)" :
* withField(field.fieldName(), field.fieldType(),
* fb -> fb.transform(field, transform)) // @link regex="transform(?=\()" target="FieldBuilder#transform"
* }
*
* @param field the field to be transformed
* @param transform the transform to apply to the field
* @return this builder
* @see FieldTransform
*/
ClassBuilder transformField(FieldModel field, FieldTransform transform);
/**
* Adds a method.
* @param name the name of the method
* Adds a method. The bit for {@link ClassFile#ACC_STATIC ACC_STATIC} flag
* cannot be modified by the {@code handler} later, and must be set through
* {@code methodFlags}.
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method
* @return this builder
* @see MethodModel
*/
ClassBuilder withMethod(Utf8Entry name,
Utf8Entry descriptor,
@@ -226,14 +268,23 @@ public sealed interface ClassBuilder
Consumer<? super MethodBuilder> handler);
/**
* Adds a method, with only a {@code Code} attribute.
* Adds a method, with only access flags and a {@link CodeModel}. The bit
* for {@link ClassFile#ACC_STATIC ACC_STATIC} flag cannot be modified by
* the {@code handler} later, and must be set through {@code methodFlags}.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* // @link substring=withMethod target="#withMethod(Utf8Entry, Utf8Entry, int, Consumer)" :
* withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)) // @link substring=withCode target="MethodBuilder#withCode"
* }
*
* @param name the name of the method
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method body
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethodBody(Utf8Entry name,
Utf8Entry descriptor,
@@ -243,13 +294,17 @@ public sealed interface ClassBuilder
}
/**
* Adds a method.
* @param name the name of the method
* Adds a method. The bit for {@link ClassFile#ACC_STATIC ACC_STATIC} flag
* cannot be modified by the {@code handler}, and must be set through
* {@code methodFlags}.
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethod(String name,
MethodTypeDesc descriptor,
@@ -262,13 +317,23 @@ public sealed interface ClassBuilder
}
/**
* Adds a method, with only a {@link CodeAttribute}.
* @param name the name of the method
* Adds a method, with only access flags and a {@link CodeModel}. The bit
* for {@link ClassFile#ACC_STATIC ACC_STATIC} flag cannot be modified by
* the {@code handler}, and must be set through {@code methodFlags}.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* // @link substring=withMethod target="#withMethod(String, MethodTypeDesc, int, Consumer)" :
* withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)) // @link substring=withCode target="MethodBuilder#withCode"
* }
*
* @param name the method name
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @param methodFlags the access flags as a bit mask, with the {@code
* ACC_STATIC} bit definitely set
* @param handler handler to supply the contents of the method body
* @return this builder
* @see MethodModel
*/
default ClassBuilder withMethodBody(String name,
MethodTypeDesc descriptor,
@@ -278,17 +343,21 @@ public sealed interface ClassBuilder
}
/**
* Adds a method by transforming a method from another class.
*
* @implNote
* <p>This method behaves as if:
* Adds a method by transforming a method from another class. The transform
* cannot modify the {@link ClassFile#ACC_STATIC ACC_STATIC} flag of the
* original method.
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withMethod(method.methodName(), method.methodType(),
* b -> b.transformMethod(method, transform));
* // @link substring=withMethod target="#withMethod(Utf8Entry, Utf8Entry, int, Consumer)" :
* withMethod(method.methodName(), method.methodType(), method.flags().flagMask(),
* mb -> mb.transform(method, transform)) // @link regex="transform(?=\()" target="MethodBuilder#transform"
* }
*
* @param method the method to be transformed
* @param transform the transform to apply to the method
* @return this builder
* @see MethodTransform
*/
ClassBuilder transformMethod(MethodModel method, MethodTransform transform);
}

View File

@@ -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,9 +27,21 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link ClassModel} or be presented to a {@link ClassBuilder}.
* Marker interface for a member element of a {@link ClassModel}. Such an
* element can appear when traversing a {@link ClassModel} unless otherwise
* specified, be supplied to a {@link ClassBuilder}, and be processed by a
* {@link ClassTransform}.
* <p>
* {@link AccessFlags}, and {@link ClassFileVersion} are member elements of a
* class that appear exactly once during the traversal of a {@link ClassModel}.
* {@link Superclass} and {@link Interfaces} may be absent or appear at most
* once. A {@link ClassBuilder} may provide an alternative superclass if it is
* not defined but required.
*
* @see ClassFileElement##membership Membership Elements
* @see MethodElement
* @see FieldElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View File

@@ -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
@@ -31,17 +31,36 @@ import java.util.function.Consumer;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A builder for a classfile or portion of a classfile. Builders are rarely
* created directly; they are passed to handlers by methods such as
* {@link ClassFile#build(ClassDesc, Consumer)} or to transforms.
* Elements of the newly built entity can be specified
* abstractly (by passing a {@link ClassFileElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for a {@link CompoundElement}, which accepts the member elements
* to be integrated into the built structure. Builders are usually passed as
* an argument to {@link Consumer} handlers, such as in {@link
* ClassFile#build(ClassDesc, Consumer)}. The handlers should deliver elements
* to a builder similar to how a {@link CompoundElement} traverses its member
* elements.
* <p>
* The basic way a builder accepts elements is through {@link #with}, which
* supports call chaining. Concrete subtypes of builders usually define extra
* methods to define elements directly to the builder, such as {@link
* ClassBuilder#withFlags(int)} or {@link CodeBuilder#aload(int)}.
* <p>
* Whether a member element can appear multiple times in a compound structure
* affects the behavior of the element in {@code ClassFileBuilder}s. If an
* element can appear at most once but multiple instances are supplied to a
* {@code ClassFileBuilder}, the last supplied instance appears on the built
* structure. If an element appears exactly once but no instance is supplied,
* an unspecified default value element may be used in that structure.
* <p>
* Due to restrictions of the {@code class} file format, certain member elements
* that can be modeled by the API cannot be represented in the built structure
* under specific circumstances. Passing such elements to the builder causes
* {@link IllegalArgumentException}. Some {@link ClassFile.Option}s control
* whether such elements should be altered or dropped to produce valid {@code
* class} files.
*
* @param <E> the element type
* @param <B> the builder type
* @param <E> the member element type
* @param <B> the self type of this builder
* @see CompoundElement
* @see ClassFileTransform
*
* @sealedGraph
* @since 24
*/
@@ -49,8 +68,15 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
extends Consumer<E> permits ClassBuilder, FieldBuilder, MethodBuilder, CodeBuilder {
/**
* Integrate the {@link ClassFileElement} into the entity being built.
* @param e the element
* Integrates the member element into the structure being built.
*
* @apiNote
* This method exists to implement {@link Consumer}; users can use {@link
* #with} for call chaining.
*
* @param e the member element
* @throws IllegalArgumentException if the member element cannot be
* represented in the {@code class} file format
*/
@Override
default void accept(E e) {
@@ -58,9 +84,12 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
}
/**
* Integrate the {@link ClassFileElement} into the entity being built.
* @param e the element
* Integrates the member element into the structure being built.
*
* @param e the member element
* @return this builder
* @throws IllegalArgumentException if the member element cannot be
* represented in the {@code class} file format
*/
B with(E e);
@@ -70,10 +99,29 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
ConstantPoolBuilder constantPool();
/**
* Apply a transform to a model, directing results to this builder.
* @param model the model to transform
* Applies a transform to a compound structure, directing results to this
* builder.
* <p>
* The transform will receive each element of the compound structure, as
* well as this builder for building the structure. The transform is free
* to preserve, remove, or replace elements as it sees fit.
* <p>
* A builder can run multiple transforms against different compound
* structures, integrating member elements of different origins.
*
* @apiNote
* Many subinterfaces have methods like {@link ClassBuilder#transformMethod}
* or {@link MethodBuilder#transformCode}. However, calling them is
* fundamentally different from calling this method: those methods call the
* {@code transform} on the child builders instead of on itself. For
* example, {@code classBuilder.transformMethod} calls {@code
* methodBuilder.transform} with a new method builder instead of calling
* {@code classBuilder.transform} on itself.
*
* @param model the structure to transform
* @param transform the transform to apply
* @return this builder
* @see ClassFileTransform
*/
default B transform(CompoundElement<E> model, ClassFileTransform<?, E, B> transform) {
@SuppressWarnings("unchecked")

View File

@@ -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,12 +25,34 @@
package java.lang.classfile;
/**
* Immutable model for a portion of (or the entirety of) a classfile. Elements
* that model parts of the classfile that have attributes will implement {@link
* AttributedElement}; elements that model complex parts of the classfile that
* themselves contain their own child elements will implement {@link
* CompoundElement}. Elements specific to various locations in the classfile
* will implement {@link ClassElement}, {@link MethodElement}, etc.
* Marker interface for structures with special capabilities in the {@code
* class} file format. {@link AttributedElement} indicates a structure has
* {@link Attribute}s. {@link CompoundElement} indicates a structure can be
* viewed as a composition of member structures, whose memberships are marked by
* {@link ClassElement}, {@link MethodElement}, {@link FieldElement}, or {@link
* CodeElement}.
*
* <h2 id="membership">Membership Elements</h2>
* {@link ClassModel}, {@link MethodModel}, {@link FieldModel}, and {@link
* CodeModel} each has a dedicated interface marking its member structures:
* {@link ClassElement}, {@link MethodElement}, {@link FieldElement}, and
* {@link CodeElement}. They can be supplied to a {@link ClassBuilder}, a
* {@link MethodBuilder}, a {@link FieldBuilder}, or a {@link CodeBuilder} to be
* included as members of the built model. Unless otherwise specified, these
* structures are delivered during the {@linkplain CompoundElement traversal} of
* the corresponding models. Some of these elements may appear at most once or
* exactly once in the traversal of the models; such elements have special
* treatment by {@link ClassFileBuilder} and are specified in their modeling
* interfaces. If such elements appear multiple times during traversal, the
* last occurrence should be used and all previous instances should be
* discarded.
* <p>
* These membership element marker interfaces are sealed; future versions of the
* Java SE Platform may define new elements to the sealed hierarchy when the
* {@code class} file format for the Java Platform evolves. Using an exhaustive
* pattern matching switch over these hierarchies indicates the user only wish
* the processing code to run on a specific version of Java Platform, and will
* fail if unknown new elements are encountered.
*
* @sealedGraph
* @since 24

View File

@@ -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,44 +25,74 @@
package java.lang.classfile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* A transformation on streams of elements. Transforms are used during
* transformation of classfile entities; a transform is provided to a method like
* {@link ClassFile#transformClass(ClassModel, ClassTransform)}, and the elements of the class,
* along with a builder, are presented to the transform.
*
* <p>The subtypes of {@linkplain
* ClassFileTransform} (e.g., {@link ClassTransform}) are functional interfaces
* that accept an element and a corresponding builder. Since any element can be
* reproduced on the builder via {@link ClassBuilder#with(ClassFileElement)}, a
* transform can easily leave elements in place, remove them, replace them, or
* augment them with other elements. This enables localized transforms to be
* represented concisely.
*
* <p>Transforms also have an {@link #atEnd(ClassFileBuilder)} method, for
* which the default implementation does nothing, so that a transform can
* perform additional building after the stream of elements is exhausted.
*
* <p>Transforms can be chained together via the {@link
* #andThen(ClassFileTransform)} method, so that the output of one becomes the
* input to another. This allows smaller units of transformation to be captured
* and reused.
*
* <p>Some transforms are stateful; for example, a transform that injects an
* annotation on a class may watch for the {@link RuntimeVisibleAnnotationsAttribute}
* element and transform it if found, but if it is not found, will generate a
* {@linkplain RuntimeVisibleAnnotationsAttribute} element containing the
* injected annotation from the {@linkplain #atEnd(ClassFileBuilder)} handler.
* To do this, the transform must accumulate some state during the traversal so
* that the end handler knows what to do. If such a transform is to be reused,
* its state must be reset for each traversal; this will happen automatically if
* the transform is created with {@link ClassTransform#ofStateful(Supplier)} (or
* corresponding methods for other classfile locations.)
* A transformation on a {@link CompoundElement} by processing its individual
* member elements and sending the results to a {@link ClassFileBuilder},
* through {@link ClassFileBuilder#transform}. A subtype of {@code
* ClassFileTransform} is defined for each subtype of {@link CompoundElement}
* and {@link ClassFileBuilder}, as shown in the sealed class hierarchy below.
* <p>
* For example, this is a basic transformation of a {@link CodeModel} that
* redirects all calls to static methods in the {@code Foo} class to the {@code
* Bar} class, preserving all other elements:
* {@snippet file="PackageSnippets.java" region=fooToBarTransform}
* Note that if no transformation of a member element is desired, the element
* should be presented to {@link ClassFileBuilder#with builder::with}. If no
* action is taken, that member element is dropped.
* <p>
* More advanced usages of transforms include {@linkplain ##start-end start or
* end handling}, {@linkplain ##stateful stateful transformation} that makes a
* decision based on previously encountered member elements, and {@linkplain
* ##composition composition} of transforms, where one transform processes the
* results of a previous transform on the input compound structure. All these
* capabilities are supported by this interface and accessible to user transform
* implementations.
* <p id="start-end">
* Users can define custom start and end handling for a transform by overriding
* {@link #atStart} and {@link #atEnd}. The start handler is called before any
* member element is processed, and the end handler is called after all member
* elements are processed. For example, the start handler can be used to inject
* extra code elements to the beginning of a code array, and the end handler,
* combined with stateful transformation, can perform cleanup actions, such as
* determining if an attribute has been merged, or if a new attribute should be
* defined. Each subtype of {@code ClassFileTransform} defines a utility method
* {@code endHandler} that returns a transform that only has end handling.
* <p id="stateful">
* Transforms can have states that persist across processing of individual
* member elements. For example, if a transform injects an annotation, the
* transform may keep track if it has encountered and presented an updated
* {@link RuntimeVisibleAnnotationsAttribute} to the builder; if it has not yet,
* it can present a new attribute containing only the injected annotation in its
* end handler. If such a transform is to be shared or reused, each returned
* transform should have its own state. Each subtype of {@code ClassFileTransform}
* defines a utility method {@code ofStateful} where a supplier creates the
* transform at its initial state each time the transform is reused.
* <p id="composition">
* Transforms can be composed via {@link #andThen}. When this transform is
* composed with another transform, it means the output member elements received
* by the {@link ClassFileBuilder} become the input elements to that other
* transform. Composition avoids building intermediate structures for multiple
* transforms to run on. Each subtype of {@code ClassFileTransform} implements
* {@link #andThen}, which generally should not be implemented by users.
* <p>
* Transforms that run on smaller structures can be lifted to its enclosing
* structures to selectively run on all enclosed smaller structures of the same
* kind. For example, a {@link CodeTransform} can be lifted via {@link
* ClassTransform#transformingMethodBodies(Predicate, CodeTransform)} to
* transform the method body of select methods in the class it runs on. This
* allows users to write small transforms and apply to larger scales.
* <p>
* Besides {@link ClassFileBuilder#transform}, there are other methods that
* accepts a transform conveniently, such as {@link ClassFile#transformClass},
* {@link ClassBuilder#transformField}, {@link ClassBuilder#transformMethod}, or
* {@link MethodBuilder#transformCode}. They are convenience methods that suit
* the majority of transformation scenarios.
*
* @param <C> the transform type
* @param <E> the element type
* @param <E> the member element type
* @param <B> the builder type
*
* @sealedGraph
@@ -79,6 +109,9 @@ public sealed interface ClassFileTransform<
* body.) If no transformation is desired, the element can be presented to
* {@link B#with(ClassFileElement)}. If the element is to be dropped, no
* action is required.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @param element the element
@@ -89,6 +122,9 @@ public sealed interface ClassFileTransform<
* Take any final action during transformation of a classfile entity. Called
* after all elements of the class are presented to {@link
* #accept(ClassFileBuilder, ClassFileElement)}.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
@@ -100,6 +136,9 @@ public sealed interface ClassFileTransform<
* Take any preliminary action during transformation of a classfile entity.
* Called before any elements of the class are presented to {@link
* #accept(ClassFileBuilder, ClassFileElement)}.
* <p>
* This method is called by the Class-File API. Users should never call
* this method.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
@@ -110,6 +149,10 @@ public sealed interface ClassFileTransform<
/**
* Chain this transform with another; elements presented to the builder of
* this transform will become the input to the next transform.
* <p>
* This method is implemented by the Class-File API. Users usually don't
* have sufficient access to Class-File API functionalities to override this
* method correctly for generic downstream transforms.
*
* @param next the downstream transform
* @return the chained transform

View File

@@ -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,32 +24,62 @@
*/
package java.lang.classfile;
import java.lang.reflect.ClassFileFormatVersion;
import jdk.internal.classfile.impl.ClassFileVersionImpl;
/**
* Models the classfile version information for a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing the elements of a {@link
* ClassModel}.
* Models the minor and major version numbers of a {@code class} file (JVMS
* {@jvms 4.1}). The {@code class} file version appears exactly once in each
* class, and is set to an unspecified default value if not explicitly provided.
* <p>
* The major versions of {@code class} file format begins at {@value
* ClassFile#JAVA_1_VERSION} for Java Platform version 1.0.2, and is continuous
* up to {@link ClassFile#latestMajorVersion()}. In general, each major version
* defines a new supported {@code class} file format, modeled by {@link
* ClassFileFormatVersion}, and supports all previous formats.
* <p>
* For major versions up to {@value ClassFile#JAVA_11_VERSION} for Java SE
* Platform 11, the minor version of any value is supported. For major versions
* {@value ClassFile#JAVA_12_VERSION} for Java SE Platform version 12 and above,
* the minor version must be {@code 0} or {@value ClassFile#PREVIEW_MINOR_VERSION}.
* The minor version {@code 0} is always supported, and represents the format
* modeled by {@link ClassFileFormatVersion}. The minor version {@code 65535}
* indicates the {@code class} file uses preview features of the Java SE
* Platform release represented by the major version. A Java Virtual Machine
* can only load such a {@code class} file if it has the same Java SE Platform
* version and the JVM has preview features enabled.
*
* @see ClassModel#majorVersion()
* @see ClassModel#minorVersion()
* @see ClassFileFormatVersion
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface ClassFileVersion
extends ClassElement
permits ClassFileVersionImpl {
/**
* {@return the major classfile version}
* {@return the major version} It is in the range of unsigned short, {@code
* [0, 65535]}.
*
* @apiNote
* Constants in {@link ClassFile} named {@code Java_#_VERSION}, where # is
* a release number, such as {@link ClassFile#JAVA_21_VERSION}, describe the
* class major versions of the Java Platform SE.
*/
int majorVersion();
/**
* {@return the minor classfile version}
* {@return the minor version} It is in the range of unsigned short, {@code
* [0, 65535]}.
*/
int minorVersion();
/**
* {@return a {@link ClassFileVersion} element}
* @param majorVersion the major classfile version
* @param minorVersion the minor classfile version
* @param majorVersion the major version
* @param minorVersion the minor version
*/
static ClassFileVersion of(int majorVersion, int minorVersion) {
return new ClassFileVersionImpl(majorVersion, minorVersion);

View File

@@ -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,7 +24,11 @@
*/
package java.lang.classfile;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.classfile.ClassFile.StackMapsOption;
import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.constant.ClassDesc;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
@@ -42,27 +46,42 @@ import static java.lang.constant.ConstantDescs.CD_Object;
import static java.util.Objects.requireNonNull;
/**
* Provides class hierarchy information for generating correct stack maps
* during code building.
* Provides class hierarchy information for {@linkplain StackMapsOption stack
* maps generation} and {@linkplain ClassFile#verify(byte[]) verification}.
* A class hierarchy resolver must be able to process all classes and interfaces
* encountered during these workloads.
*
* @see ClassFile.ClassHierarchyResolverOption
* @see StackMapTableAttribute
* @jvms 4.10.1.2 Verification Type System
* @since 24
*/
@FunctionalInterface
public interface ClassHierarchyResolver {
/**
* {@return the default instance of {@linkplain ClassHierarchyResolver} that
* {@return the default instance of {@code ClassHierarchyResolver} that
* gets {@link ClassHierarchyInfo} from system class loader with reflection}
* This default instance cannot load classes from other class loaders, such
* as the caller's class loader; it also loads the system classes if they
* are not yet loaded, which makes it unsuitable for instrumentation.
*/
static ClassHierarchyResolver defaultResolver() {
return ClassHierarchyImpl.DEFAULT_RESOLVER;
}
/**
* {@return the {@link ClassHierarchyInfo} for a given class name, or null
* if the name is unknown to the resolver}
* {@return the {@code ClassHierarchyInfo} for a given class name, or {@code
* null} if the name is unknown to the resolver}
* <p>
* This method is called by the Class-File API to obtain the hierarchy
* information of a class or interface; users should not call this method.
* The symbolic descriptor passed by the Class-File API always represents
* a class or interface.
*
* @param classDesc descriptor of the class
* @throws IllegalArgumentException if a class shouldn't be queried for hierarchy
* @throws IllegalArgumentException if a class shouldn't be queried for
* hierarchy, such as when it is inaccessible
*/
ClassHierarchyInfo getClassInfo(ClassDesc classDesc);
@@ -78,6 +97,7 @@ public interface ClassHierarchyResolver {
*
* @param superClass descriptor of the super class, may be {@code null}
* @return the info indicating the super class
* @see Superclass
*/
static ClassHierarchyInfo ofClass(ClassDesc superClass) {
return new ClassHierarchyImpl.ClassHierarchyInfoImpl(superClass, false);
@@ -94,14 +114,15 @@ public interface ClassHierarchyResolver {
}
/**
* Chains this {@linkplain ClassHierarchyResolver} with another to be
* consulted if this resolver does not know about the specified class.
* Chains this {@code ClassHierarchyResolver} with another to be consulted
* if this resolver does not know about the specified class.
*
* @implSpec
* The default implementation returns resolver implemented to query {@code
* other} resolver in case this resolver returns {@code null}.
*
* @param other the other resolver
* @return the chained resolver
*
* @implSpec The default implementation returns resolver implemented to ask
* other resolver in cases where this resolver returns {@code null}.
*/
default ClassHierarchyResolver orElse(ClassHierarchyResolver other) {
requireNonNull(other);
@@ -117,32 +138,32 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a ClassHierarchyResolver that caches class hierarchy information from this
* resolver. The returned resolver will not update if delegate resolver returns differently.
* The thread safety of the returned resolver depends on the thread safety of the map
* {@return a {@code ClassHierarchyResolver} that caches class hierarchy
* information from this resolver} The returned resolver will not update if
* the query results from this resolver changed over time. The thread
* safety of the returned resolver depends on the thread safety of the map
* returned by the {@code cacheFactory}.
*
* @param cacheFactory the factory for the cache
* @return the ClassHierarchyResolver with caching
* @implSpec
* The default implementation returns a resolver holding an instance of the
* cache map provided by the {@code cacheFactory}. It looks up in the cache
* map, or if a class name has not yet been queried, queries this resolver
* and caches the result, including a {@code null} that indicates unknown
* class names. The cache map may refuse {@code null} keys and values.
*
* @implSpec The default implementation returns resolver holding an instance
* of the cache map provided by the {@code cacheFactory}. It asks
* the cache map always first and fills the cache map with all
* resolved and also unresolved class info. The cache map may refuse
* {@code null} keys and values.
* @param cacheFactory the factory for the cache
*/
default ClassHierarchyResolver cached(Supplier<Map<ClassDesc, ClassHierarchyInfo>> cacheFactory) {
return new ClassHierarchyImpl.CachedClassHierarchyResolver(this, cacheFactory.get());
}
/**
* Returns a ClassHierarchyResolver that caches class hierarchy information from this
* resolver. The returned resolver will not update if delegate resolver returns differently.
* The returned resolver is not thread-safe.
* {@return a {@code ClassHierarchyResolver} that caches class hierarchy
* information from this resolver} The returned resolver will not update if
* the query results from this resolver changed over time. The returned
* resolver is not thread-safe.
* {@snippet file="PackageSnippets.java" region="lookup-class-hierarchy-resolver"}
*
* @return the ClassHierarchyResolver
*
* @implSpec The default implementation calls {@link #cached(Supplier)} with
* {@link HashMap} supplier as {@code cacheFactory}.
*/
@@ -160,24 +181,24 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from classfiles located by a mapping function. The mapping function
* should return null if it cannot provide a mapping for a classfile. Any IOException
* from the provided input stream is rethrown as an UncheckedIOException.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from {@code class} files returned by a mapping function} The
* mapping function should return {@code null} if it cannot provide a
* {@code class} file for a class name. Any {@link IOException} from the
* provided input stream is rethrown as an {@link UncheckedIOException}
* in {@link #getClassInfo(ClassDesc)}.
*
* @param classStreamResolver maps class descriptors to classfile input streams
* @return the {@linkplain ClassHierarchyResolver}
* @param classStreamResolver maps class descriptors to {@code class} file input streams
*/
static ClassHierarchyResolver ofResourceParsing(Function<ClassDesc, InputStream> classStreamResolver) {
return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(requireNonNull(classStreamResolver));
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from classfiles located by a class loader.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from {@code class} files located by a class loader}
*
* @param loader the class loader, to find class files
* @return the {@linkplain ClassHierarchyResolver}
*/
static ClassHierarchyResolver ofResourceParsing(ClassLoader loader) {
requireNonNull(loader);
@@ -190,24 +211,22 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from collections of class hierarchy metadata
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information from collections of class hierarchy metadata}
*
* @param interfaces a collection of classes known to be interfaces
* @param classToSuperClass a map from classes to their super classes
* @return the {@linkplain ClassHierarchyResolver}
*/
static ClassHierarchyResolver of(Collection<ClassDesc> interfaces,
Map<ClassDesc, ClassDesc> classToSuperClass) {
Map<ClassDesc, ClassDesc> classToSuperClass) {
return new StaticClassHierarchyResolver(interfaces, classToSuperClass);
}
/**
* Returns a ClassHierarchyResolver that extracts class hierarchy information via
* the Reflection API with a {@linkplain ClassLoader}.
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information via classes loaded by a class loader with reflection}
*
* @param loader the class loader
* @return the class hierarchy resolver
*/
static ClassHierarchyResolver ofClassLoading(ClassLoader loader) {
requireNonNull(loader);
@@ -224,13 +243,13 @@ public interface ClassHierarchyResolver {
}
/**
* Returns a ClassHierarchyResolver that extracts class hierarchy information via
* the Reflection API with a {@linkplain MethodHandles.Lookup Lookup}. If the class
* resolved is inaccessible to the given lookup, it throws {@link
* {@return a {@code ClassHierarchyResolver} that extracts class hierarchy
* information via classes accessible to a {@link MethodHandles.Lookup}
* with reflection} If the class resolved is inaccessible to the given
* lookup, {@link #getClassInfo(ClassDesc)} throws {@link
* IllegalArgumentException} instead of returning {@code null}.
*
* @param lookup the lookup, must be able to access classes to resolve
* @return the class hierarchy resolver
*/
static ClassHierarchyResolver ofClassLoading(MethodHandles.Lookup lookup) {
requireNonNull(lookup);

View File

@@ -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,18 +25,41 @@
package java.lang.classfile;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.attribute.ModuleAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.ClassImpl;
/**
* Models a classfile. The contents of the classfile can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a {@code class} file. A {@code class} file can be viewed as a
* {@linkplain CompoundElement composition} of {@link ClassElement}s, or by
* random access via accessor methods if only specific parts of the {@code
* class} file is needed.
* <p>
* Use {@link ClassFile#parse(byte[])}, which parses the binary data of a {@code
* class} file into a model, to obtain a {@code ClassModel}.
* <p>
* To construct a {@code class} file, use {@link ClassFile#build(ClassDesc,
* Consumer)}. {@link ClassFile#transformClass(ClassModel, ClassTransform)}
* allows creating a new class by selectively processing the original class
* elements and directing the results to a class builder.
* <p>
* A class holds attributes, most of which are accessible as member elements.
* {@link BootstrapMethodsAttribute} can only be accessed via {@linkplain
* AttributedElement explicit attribute reading}, as it is modeled as part of
* the {@linkplain #constantPool() constant pool}.
*
* @see ClassFile#parse(byte[])
* @see ClassTransform
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface ClassModel
@@ -45,19 +68,35 @@ public sealed interface ClassModel
/**
* {@return the constant pool for this class}
*
* @see ConstantPoolBuilder#of(ClassModel)
*/
ConstantPool constantPool();
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#CLASS
*/
AccessFlags flags();
/** {@return the constant pool entry describing the name of this class} */
ClassEntry thisClass();
/** {@return the major classfile version} */
/**
* {@return the major version of this class} It is in the range of unsigned
* short, {@code [0, 65535]}.
*
* @see ClassFileVersion
*/
int majorVersion();
/** {@return the minor classfile version} */
/**
* {@return the minor version of this class} It is in the range of unsigned
* short, {@code [0, 65535]}.
*
* @see ClassFileVersion
*/
int minorVersion();
/** {@return the fields of this class} */
@@ -66,12 +105,28 @@ public sealed interface ClassModel
/** {@return the methods of this class} */
List<MethodModel> methods();
/** {@return the superclass of this class, if there is one} */
/**
* {@return the superclass of this class, if there is one}
* This {@code class} file may have no superclass if this represents a
* {@linkplain #isModuleInfo() module descriptor} or the {@link Object}
* class; otherwise, it must have a superclass. If this is an interface,
* the superclass must be {@link Object}.
*
* @see Superclass
*/
Optional<ClassEntry> superclass();
/** {@return the interfaces implemented by this class} */
/**
* {@return the interfaces implemented by this class}
*
* @see Interfaces
*/
List<ClassEntry> interfaces();
/** {@return whether this class is a module descriptor} */
/**
* {@return whether this {@code class} file is a module descriptor}
*
* @see ClassFile#buildModule(ModuleAttribute, Consumer)
*/
boolean isModuleInfo();
}

View File

@@ -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
@@ -35,12 +35,21 @@ import java.util.function.Function;
import jdk.internal.classfile.impl.ClassReaderImpl;
/**
* Supports reading from a classfile. Methods are provided to read data of
* various numeric types (e.g., {@code u2}, {@code u4}) at a given offset within
* the classfile, copying raw bytes, and reading constant pool entries.
* Encapsulates additional reading context such as mappers for custom attributes
* and processing options.
* Advanced {@code class} file reading support for {@link AttributeMapper}s.
* Supports reading arbitrary offsets within a {@code class} file and reading
* data of various numeric types (e.g., {@code u2}, {@code u4}) in addition to
* constant pool access.
* <p>
* All numeric values in the {@code class} file format are {@linkplain
* java.nio.ByteOrder#BIG_ENDIAN big endian}.
* <p>
* Unless otherwise specified, all out-of-bounds access result in an {@link
* IllegalArgumentException} to indicate the {@code class} file data is
* malformed. Since the {@code class} file data is arbitrary, users should
* sanity-check the structural integrity of the data before attempting to
* interpret the potentially malformed data.
*
* @see AttributeMapper#readAttribute(AttributedElement, ClassReader, int)
* @since 24
*/
public sealed interface ClassReader extends ConstantPool
@@ -56,29 +65,41 @@ public sealed interface ClassReader extends ConstantPool
// Class context
/** {@return the access flags for the class, as a bit mask } */
/**
* {@return the access flags for the class, as a bit mask}
*
* @see ClassModel#flags()
*/
int flags();
/** {@return the constant pool entry describing the name of class} */
/**
* {@return the constant pool entry describing the name of class}
*
* @see ClassModel#thisClass()
*/
ClassEntry thisClassEntry();
/** {@return the constant pool entry describing the name of the superclass, if any} */
/**
* {@return the constant pool entry describing the name of the superclass, if any}
*
* @see ClassModel#superclass()
*/
Optional<ClassEntry> superclassEntry();
/** {@return the length of the classfile, in bytes} */
/** {@return the length of the {@code class} file, in number of bytes} */
int classfileLength();
// Constant pool
/**
* {@return the constant pool entry whose index is given at the specified
* offset within the classfile}
* offset within the {@code class} file}
*
* @apiNote
* If only a particular type of entry is expected, use {@link #readEntry(
* int, Class) readEntry(int, Class)}.
*
* @param offset the offset of the index within the classfile
* @param offset the offset of the index within the {@code class} file
* @throws ConstantPoolException if the index is out of range of the
* constant pool size, or zero
*/
@@ -86,9 +107,9 @@ public sealed interface ClassReader extends ConstantPool
/**
* {@return the constant pool entry of a given type whose index is given
* at the specified offset within the classfile}
* at the specified offset within the {@code class} file}
* @param <T> the entry type
* @param offset the offset of the index within the classfile
* @param offset the offset of the index within the {@code class} file
* @param cls the entry type
* @throws ConstantPoolException if the index is out of range of the
* constant pool size, or zero, or the entry is not of the given type
@@ -97,14 +118,14 @@ public sealed interface ClassReader extends ConstantPool
/**
* {@return the constant pool entry whose index is given at the specified
* offset within the classfile, or null if the index at the specified
* offset is zero}
* offset within the {@code class} file, or {@code null} if the index at the
* specified offset is zero}
*
* @apiNote
* If only a particular type of entry is expected, use {@link #readEntryOrNull(
* int, Class) readEntryOrNull(int, Class)}.
*
* @param offset the offset of the index within the classfile
* @param offset the offset of the index within the {@code class} file
* @throws ConstantPoolException if the index is out of range of the
* constant pool size
*/
@@ -112,11 +133,11 @@ public sealed interface ClassReader extends ConstantPool
/**
* {@return the constant pool entry of a given type whose index is given
* at the specified offset within the classfile, or null if the index at
* the specified offset is zero}
* at the specified offset within the {@code class} file, or {@code null} if
* the index at the specified offset is zero}
*
* @param <T> the entry type
* @param offset the offset of the index within the classfile
* @param offset the offset of the index within the {@code class} file
* @param cls the entry type
* @throws ConstantPoolException if the index is out of range of the
* constant pool size, or zero, or the entry is not of the given type
@@ -124,65 +145,89 @@ public sealed interface ClassReader extends ConstantPool
<T extends PoolEntry> T readEntryOrNull(int offset, Class<T> cls);
/**
* {@return the unsigned byte at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the unsigned byte at the specified offset within the {@code
* class} file} Reads a byte and zero-extends it to an {@code int}.
*
* @param offset the offset within the {@code class} file
*/
int readU1(int offset);
/**
* {@return the unsigned short at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the unsigned short at the specified offset within the {@code
* class} file} Reads a 2-byte value and zero-extends it to an {@code int}.
*
* @param offset the offset within the {@code class} file
*/
int readU2(int offset);
/**
* {@return the signed byte at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the signed byte at the specified offset within the {@code class}
* file} Reads a byte and sign-extends it to an {@code int}.
*
* @param offset the offset within the {@code class} file
*/
int readS1(int offset);
/**
* {@return the signed byte at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the signed byte at the specified offset within the {@code class}
* file} Reads a 2-byte value and sign-extends it to an {@code int}.
*
* @param offset the offset within the {@code class} file
*/
int readS2(int offset);
/**
* {@return the signed int at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the signed int at the specified offset within the {@code class}
* file} Reads 4 bytes of value.
*
* @param offset the offset within the {@code class} file
*/
int readInt(int offset);
/**
* {@return the signed long at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the signed long at the specified offset within the {@code class}
* file} Reads 8 bytes of value.
*
* @param offset the offset within the {@code class} file
*/
long readLong(int offset);
/**
* {@return the float value at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the float value at the specified offset within the {@code class}
* file} Reads 4 bytes of value.
* <p>
* In the conversions, all NaN values of the {@code float} may or may not be
* collapsed into a single {@linkplain Float#NaN "canonical" NaN value}.
*
* @param offset the offset within the {@code class} file
*/
float readFloat(int offset);
/**
* {@return the double value at the specified offset within the classfile}
* @param offset the offset within the classfile
* {@return the double value at the specified offset within the {@code
* class} file} Reads 8 bytes of value.
* <p>
* In the conversions, all NaN values of the {@code double} may or may not
* be collapsed into a single {@linkplain Double#NaN "canonical" NaN value}.
*
* @param offset the offset within the {@code class} file
*/
double readDouble(int offset);
/**
* {@return a copy of the bytes at the specified range in the classfile}
* @param offset the offset within the classfile
* {@return a copy of the bytes at the specified range in the {@code class}
* file}
*
* @param offset the offset within the {@code class} file
* @param len the length of the range
*/
byte[] readBytes(int offset, int len);
/**
* Copy a range of bytes from the classfile to a {@link BufWriter}
* Copy a range of bytes from the {@code class} file to a {@link BufWriter}.
*
* @param buf the {@linkplain BufWriter}
* @param offset the offset within the classfile
* @param offset the offset within the {@code class} file
* @param len the length of the range
*/
void copyBytesTo(BufWriter buf, int offset, int len);

View File

@@ -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,6 +24,7 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.SignatureAttribute;
import java.util.List;
import jdk.internal.classfile.impl.SignaturesImpl;
@@ -31,27 +32,53 @@ import jdk.internal.classfile.impl.SignaturesImpl;
import static java.util.Objects.requireNonNull;
/**
* Models the generic signature of a class file, as defined by JVMS {@jvms 4.7.9}.
* Models the generic signature of a class or interface, as defined by JVMS
* {@jvms 4.7.9.1}.
*
* @see Class
* @see SignatureAttribute
* @jls 8.1 Class Declarations
* @jls 9.1 Interface Declarations
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface ClassSignature
permits SignaturesImpl.ClassSignatureImpl {
/** {@return the type parameters of this class} */
/**
* {@return the type parameters of this class or interface, may be empty}
*
* @see Class#getTypeParameters()
* @jls 8.1.2 Generic Classes and Type Parameters
* @jls 9.1.2 Generic Interfaces and Type Parameters
*/
List<Signature.TypeParam> typeParameters();
/** {@return the instantiation of the superclass in this signature} */
/**
* {@return the instantiation of the superclass in this signature}
* Interfaces return a signature representing the {@link Object} class.
*
* @see Class#getGenericSuperclass()
* @jls 8.1.4 Superclasses and Subclasses
*/
Signature.ClassTypeSig superclassSignature();
/** {@return the instantiation of the interfaces in this signature} */
/**
* {@return the instantiation of the interfaces in this signature, may be
* empty}
*
* @see Class#getGenericInterfaces()
* @jls 8.1.5 Superinterfaces
* @jls 9.1.3 Superinterfaces and Subinterfaces
*/
List<Signature.ClassTypeSig> superinterfaceSignatures();
/** {@return the raw signature string} */
String signatureString();
/**
* {@return a class signature}
* {@return a class signature with no type parameter declaration}
*
* @param superclassSignature the superclass
* @param superinterfaceSignatures the interfaces
*/
@@ -62,7 +89,7 @@ public sealed interface ClassSignature
/**
* {@return a class signature}
* @param typeParameters the type parameters
* @param typeParameters the type parameters, may be empty
* @param superclassSignature the superclass
* @param superinterfaceSignatures the interfaces
*/
@@ -76,9 +103,11 @@ public sealed interface ClassSignature
}
/**
* Parses a raw class signature string into a {@linkplain Signature}
* Parses a raw class signature string into a {@linkplain Signature}.
*
* @param classSignature the raw class signature string
* @return class signature
* @throws IllegalArgumentException if the string is not a valid class signature string
*/
public static ClassSignature parseFrom(String classSignature) {
return new SignaturesImpl(classSignature).parseClassSignature();

View File

@@ -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
@@ -35,9 +35,12 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link ClassElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
*
* @see ClassFileTransform
*
* @see ClassModel
* @see ClassFile#transformClass(ClassModel, ClassTransform)
* @since 24
*/
@FunctionalInterface
@@ -45,7 +48,7 @@ public non-sealed interface ClassTransform
extends ClassFileTransform<ClassTransform, ClassElement, ClassBuilder> {
/**
* A class transform that sends all elements to the builder.
* A class transform that passes all elements to the builder.
*/
static final ClassTransform ACCEPT_ALL = new ClassTransform() {
@Override
@@ -55,7 +58,7 @@ public non-sealed interface ClassTransform
};
/**
* Create a stateful class transform from a {@link Supplier}. The supplier
* Creates a stateful class transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@@ -67,7 +70,7 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that passes each element through to the builder,
* Creates a class transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@@ -89,8 +92,8 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
* Creates a class transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} returns true for.
*
* @param filter the predicate that determines which elements to drop
* @return the class transform
@@ -104,8 +107,10 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
* Creates a class transform that transforms {@link MethodModel} elements
* with the supplied method transform for methods that the supplied {@link
* Predicate} returns true for, passing other elements through to the
* builder.
*
* @param filter a predicate that determines which methods to transform
* @param xform the method transform
@@ -117,8 +122,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
* Creates a class transform that transforms {@link MethodModel} elements
* with the supplied method transform, passing other elements through to the
* builder.
*
* @param xform the method transform
* @return the class transform
@@ -128,8 +134,10 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
* Creates a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform for
* methods that the supplied {@link Predicate} returns true for, passing
* other elements through to the builder.
*
* @param filter a predicate that determines which methods to transform
* @param xform the code transform
@@ -141,8 +149,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
* Creates a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform, passing
* other elements through to the builder.
*
* @param xform the code transform
* @return the class transform
@@ -152,8 +161,9 @@ public non-sealed interface ClassTransform
}
/**
* Create a class transform that transforms {@link FieldModel} elements
* with the supplied field transform.
* Creates a class transform that transforms {@link FieldModel} elements
* with the supplied field transform, passing other elements through to the
* builder.
*
* @param xform the field transform
* @return the class transform

View File

@@ -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,13 +29,20 @@ import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import java.lang.classfile.attribute.StackMapTableAttribute;
/**
* A marker interface for elements that can appear when traversing
* a {@link CodeModel} or be presented to a {@link CodeBuilder}. Code elements
* are either an {@link Instruction}, which models an instruction in the body
* of a method, or a {@link PseudoInstruction}, which models metadata from
* the code attribute, such as line number metadata, local variable metadata,
* exception metadata, label target metadata, etc.
* Marker interface for a member element of a {@link CodeModel}. Such an
* element can appear when traversing a {@link CodeModel} unless otherwise
* specified, be supplied to a {@link CodeBuilder}, and be processed by a
* {@link CodeTransform}.
* <p>
* Code elements can be categorized into {@link Instruction}, {@link
* PseudoInstruction}, and {@link Attribute}. Unlike in other {@link
* CompoundElement}, the order of elements for all {@link Instruction}s and some
* {@link PseudoInstruction}s is significant.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see MethodElement
* @see FieldElement
* @sealedGraph
* @since 24
*/

View File

@@ -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,17 +25,44 @@
package java.lang.classfile;
import java.lang.classfile.ClassFile.DeadLabelsOption;
import java.lang.classfile.ClassFile.DebugElementsOption;
import java.lang.classfile.ClassFile.LineNumbersOption;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.classfile.instruction.ExceptionCatch;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedCodeBuilder;
/**
* Models the body of a method (the {@code Code} attribute). The instructions
* of the method body are accessed via a streaming view.
* Models the body of a method (the {@code Code} attribute). A {@code Code}
* attribute is viewed as a {@linkplain CompoundElement composition} of {@link
* CodeElement}s, which is the only way to access {@link Instruction}s; the
* order of elements of a code model is significant.
* <p>
* A {@code CodeModel} is obtained from {@link MethodModel#code()}, or in the
* traversal of the member elements of a method.
* <p>
* {@link MethodBuilder#withCode} is the main way to build code models. {@link
* MethodBuilder#transformCode} and {@link CodeBuilder#transforming} allow
* creating new {@code Code} attributes by selectively processing the original
* code elements and directing the results to a code builder.
* <p>
* A {@code Code} attribute holds attributes, but they are usually not member
* elements, but are decomposed to {@link PseudoInstruction}, accessible
* according to {@link DeadLabelsOption}, {@link DebugElementsOption}, and
* {@link LineNumbersOption}. {@link StackMapTableAttribute} can only be
* accessed via {@linkplain AttributedElement explicit attribute reading}, as it
* is considered a derived property from the code body.
*
* @see MethodModel#code()
* @see CodeTransform
* @see CodeAttribute
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/
public sealed interface CodeModel

View File

@@ -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,10 +32,22 @@ import jdk.internal.classfile.impl.TransformImpl;
import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link CodeElement}.
*
* @see ClassFileTransform
* A transformation on streams of {@link CodeElement}. The stream can come
* from a {@link CodeModel}, or a handler to a {@link CodeBuilder} as in
* {@link CodeBuilder#transforming}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A code transform can be lifted to a method or a class transform via {@link
* MethodTransform#transformingCode(CodeTransform)} and {@link
* ClassTransform#transformingMethodBodies(CodeTransform)}, transforming only
* the {@link CodeModel} within those structures and passing all other elements
* to the builders.
*
* @see CodeModel
* @see MethodBuilder#transformCode
* @see CodeBuilder#transforming
* @since 24
*/
@FunctionalInterface
@@ -43,7 +55,7 @@ public non-sealed interface CodeTransform
extends ClassFileTransform<CodeTransform, CodeElement, CodeBuilder> {
/**
* A code transform that sends all elements to the builder.
* A code transform that passes all elements to the builder.
*/
CodeTransform ACCEPT_ALL = new CodeTransform() {
@Override
@@ -53,7 +65,7 @@ public non-sealed interface CodeTransform
};
/**
* Create a stateful code transform from a {@link Supplier}. The supplier
* Creates a stateful code transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@@ -65,7 +77,7 @@ public non-sealed interface CodeTransform
}
/**
* Create a code transform that passes each element through to the builder,
* Creates a code transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete

View File

@@ -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
@@ -34,15 +34,29 @@ import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import jdk.internal.classfile.components.ClassPrinter;
/**
* A {@link ClassFileElement} that has complex structure defined in terms of
* other classfile elements, such as a method, field, method body, or entire
* class. When encountering a {@linkplain CompoundElement}, clients have the
* option to treat the element as a single entity (e.g., an entire method)
* or to traverse the contents of that element with the methods in this class
* (e.g., {@link #forEach(Consumer)}, etc.)
* @param <E> the element type
* A {@code class} file structure that can be viewed as a composition of its
* member structures. {@code CompoundElement} allows users to traverse these
* member elements with {@link #forEach(Consumer)} or {@link #elementStream()},
* or buffer the elements obtained from the traversal through {@link
* #iterator()} or {@link #elementList()}.
* <p>
* Unless otherwise specified, all member elements of compatible type will be
* presented during the traversal if they exist in this element. Some member
* elements specify that they may appear at most once in this element; if such
* elements are presented multiple times, the latest occurrence is authentic and
* all previous occurrences should be ignored.
* <p>
* {@code CompoundElement}s can be constructed by {@link ClassFileBuilder}s.
* {@link ClassFileBuilder#transform(CompoundElement, ClassFileTransform)}
* provides an easy way to create a new structure by selectively processing
* the original member structures and directing the results to the builder.
*
* @param <E> the member element type
* @see ClassFileElement##membership Membership Elements
* @see ClassFileBuilder
* @sealedGraph
* @since 24
*/
@@ -50,15 +64,16 @@ public sealed interface CompoundElement<E extends ClassFileElement>
extends ClassFileElement, Iterable<E>
permits ClassModel, CodeModel, FieldModel, MethodModel, jdk.internal.classfile.impl.AbstractUnboundModel {
/**
* Invoke the provided handler with each element contained in this
* compound element
* Invokes the provided handler with each member element in this compound
* element.
*
* @param consumer the handler
*/
@Override
void forEach(Consumer<? super E> consumer);
/**
* {@return an {@link Iterator} describing all the elements contained in this
* {@return an {@link Iterator} describing all member elements in this
* compound element}
*/
@Override
@@ -67,8 +82,8 @@ public sealed interface CompoundElement<E extends ClassFileElement>
}
/**
* {@return a {@link Stream} containing all the elements contained in this
* compound element}
* {@return a {@link Stream} containing all member elements in this compound
* element}
*/
default Stream<E> elementStream() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
@@ -78,8 +93,8 @@ public sealed interface CompoundElement<E extends ClassFileElement>
}
/**
* {@return an {@link List} containing all the elements contained in this
* compound element}
* {@return a {@link List} containing all member elements in this compound
* element}
*/
default List<E> elementList() {
List<E> list = new ArrayList<>();
@@ -92,4 +107,16 @@ public sealed interface CompoundElement<E extends ClassFileElement>
return Collections.unmodifiableList(list);
}
/**
* {@return a text representation of the compound element and its contents
* for debugging purposes}
*
* The format, structure and exact contents of the returned string are not
* specified and may change at any time in the future.
*/
default String toDebugString() {
StringBuilder text = new StringBuilder();
ClassPrinter.toYaml(this, ClassPrinter.Verbosity.TRACE_ALL, text::append);
return text.toString();
}
}

View File

@@ -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,16 +24,28 @@
*/
package java.lang.classfile;
import java.lang.classfile.constantpool.PoolEntry;
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* Models a non-standard attribute of a classfile. Clients should extend
* this class to provide an implementation class for non-standard attributes,
* and provide an {@link AttributeMapper} to mediate between the classfile
* format and the {@linkplain CustomAttribute} representation.
* @param <T> the custom attribute type
* Models a user-defined attribute in a {@code class} file. API models for
* user-defined attributes should extend this class. A user-defined attribute
* should also have an {@link AttributeMapper} defined, which will be returned
* by {@link #attributeMapper}, and registered to the {@link
* ClassFile.AttributeMapperOption} so the user-defined attributes can be read.
* <p>
* User-defined attributes are currently not delivered in the traversal of a
* {@link CodeModel}.
* <p>
* Accessor methods on user-defined attributes read from {@code class} files
* may throw {@link IllegalArgumentException} if the attribute model is lazily
* evaluated, and the evaluation encounters malformed {@code class} file format
* for the attribute.
*
* @param <T> the custom attribute type
* @see java.lang.classfile.attribute
* @since 24
*/
public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>
@@ -42,7 +54,8 @@ public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>
private final AttributeMapper<T> mapper;
/**
* Construct a {@linkplain CustomAttribute}.
* Constructor for subclasses to call.
*
* @param mapper the attribute mapper
*/
protected CustomAttribute(AttributeMapper<T> mapper) {
@@ -54,6 +67,17 @@ public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>
return mapper;
}
/**
* {@inheritDoc}
*
* @implSpec
* The default implementation returns a {@code Utf8Entry} suitable for
* writing only, which may be {@linkplain PoolEntry##unbound unbound}.
* Subclasses representing attributes read from {@code class} files must
* override this method.
*
* @see AttributeMapper#readAttribute
*/
@Override
public Utf8Entry attributeName() {
return TemporaryConstantPool.INSTANCE.utf8Entry(mapper.name());

View File

@@ -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,7 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.function.Consumer;
@@ -34,14 +34,17 @@ import jdk.internal.classfile.impl.ChainedFieldBuilder;
import jdk.internal.classfile.impl.TerminalFieldBuilder;
/**
* A builder for fields. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withField(Utf8Entry, Utf8Entry, Consumer)}
* or to field transforms. The elements of a field can be specified
* abstractly (by passing a {@link FieldElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for fields. The main way to obtain a field builder is via {@link
* ClassBuilder#withField(String, ClassDesc, Consumer)}. The {@linkplain
* ClassBuilder#withField(String, ClassDesc, int) access flag overload} is
* useful if no attribute needs to be configured, skipping the handler.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see ClassBuilder#withField(String, ClassDesc, Consumer)
* @see FieldModel
* @see FieldTransform
*
* @since 24
*/
public sealed interface FieldBuilder
@@ -50,8 +53,12 @@ public sealed interface FieldBuilder
/**
* Sets the field access flags.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#FIELD
* @see ClassBuilder#withField(String, ClassDesc, int)
*/
default FieldBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.FIELD, flags));
@@ -59,8 +66,12 @@ public sealed interface FieldBuilder
/**
* Sets the field access flags.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @see AccessFlags
* @see AccessFlag.Location#FIELD
* @see ClassBuilder#withField(String, ClassDesc, int)
*/
default FieldBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.FIELD, flags));

View File

@@ -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,9 +27,18 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link FieldModel} or be presented to a {@link FieldBuilder}.
* Marker interface for a member element of a {@link FieldModel}. Such an
* element can appear when traversing a {@link FieldModel} unless otherwise
* specified, be supplied to a {@link FieldBuilder}, and be processed by a
* {@link FieldTransform}.
* <p>
* {@link AccessFlags} is the only member element of a field that appear exactly
* once during the traversal of a {@link FieldModel}.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see MethodElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View File

@@ -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,24 +27,43 @@ package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedFieldBuilder;
import jdk.internal.classfile.impl.FieldImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models a field. The contents of the field can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a field. A field can be viewed as a {@linkplain CompoundElement
* composition} of {@link FieldElement}s, or by random access via accessor
* methods if only specific parts of the field is needed.
* <p>
* Fields can be obtained from {@link ClassModel#fields()}, or in the traversal
* of member elements of a class.
* <p>
* {@link ClassBuilder#withField(String, ClassDesc, Consumer)} is the main way
* to construct fields. {@link ClassBuilder#transformField} allows creating a
* new field by selectively processing the original field elements and directing
* the results to a field builder.
* <p>
* All field attributes are accessible as member elements.
*
* @see ClassModel#fields()
* @see FieldTransform
* @jvms 4.5 Fields
* @since 24
*/
public sealed interface FieldModel
extends CompoundElement<FieldElement>, AttributedElement, ClassElement
permits BufferedFieldBuilder.Model, FieldImpl {
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#FIELD
*/
AccessFlags flags();
/** {@return the class model this field is a member of, if known} */
@@ -53,10 +72,10 @@ public sealed interface FieldModel
/** {@return the name of this field} */
Utf8Entry fieldName();
/** {@return the field descriptor of this field} */
/** {@return the field descriptor string of this field} */
Utf8Entry fieldType();
/** {@return the field descriptor of this field, as a symbolic descriptor} */
/** {@return the field type, as a symbolic descriptor} */
default ClassDesc fieldTypeSymbol() {
return Util.fieldTypeSymbol(fieldType());
}

View File

@@ -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
@@ -34,9 +34,17 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link FieldElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A field transform can be lifted to a class transform via {@link
* ClassTransform#transformingFields(FieldTransform)}, transforming only
* the {@link FieldModel} among the class members and passing all other elements
* to the builders.
*
* @see ClassFileTransform
*
* @see FieldModel
* @see ClassBuilder#transformField
* @since 24
*/
@FunctionalInterface
@@ -44,7 +52,7 @@ public non-sealed interface FieldTransform
extends ClassFileTransform<FieldTransform, FieldElement, FieldBuilder> {
/**
* A field transform that sends all elements to the builder.
* A field transform that passes all elements to the builder.
*/
FieldTransform ACCEPT_ALL = new FieldTransform() {
@Override
@@ -54,7 +62,7 @@ public non-sealed interface FieldTransform
};
/**
* Create a stateful field transform from a {@link Supplier}. The supplier
* Creates a stateful field transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@@ -66,7 +74,7 @@ public non-sealed interface FieldTransform
}
/**
* Create a field transform that passes each element through to the builder,
* Creates a field transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@@ -88,7 +96,7 @@ public non-sealed interface FieldTransform
}
/**
* Create a field transform that passes each element through to the builder,
* Creates a field transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop

View File

@@ -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,13 +25,23 @@
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.*;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models an executable instruction in a method body.
* Models an executable instruction in the {@code code} array of the {@link
* CodeAttribute Code} attribute of a method. The order of instructions in
* a {@link CodeModel} is significant.
* <p>
* The {@link #opcode() opcode} identifies the operation of an instruction.
* Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface
* for instructions.
*
* @see Opcode
* @jvms 6.5 Instructions
* @sealedGraph
* @since 24
*/
public sealed interface Instruction extends CodeElement
@@ -46,12 +56,14 @@ public sealed interface Instruction extends CodeElement
ThrowInstruction, TypeCheckInstruction, AbstractInstruction {
/**
* {@return the opcode of this instruction}
* {@return the operation of this instruction}
*/
Opcode opcode();
/**
* {@return the size in bytes of this instruction}
* This value is equal to {@link Opcode#sizeIfFixed()
* opcode().sizeIfFixed()} if it is not {@code -1}.
*/
int sizeInBytes();
}

View File

@@ -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,16 +33,22 @@ import jdk.internal.classfile.impl.InterfacesImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models the interfaces of a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing a {@link ClassModel}.
* Models the interfaces (JVMS {@jvms 4.1}) of a class. An {@code Interfaces}
* appears at most once in a {@link ClassModel}: if it does not appear, the
* class has no interfaces, which is equivalent to an {@code Interfaces} whose
* {@link #interfaces()} returns an empty list. A {@link ClassBuilder} sets
* the interfaces to an empty list if the interfaces is not supplied.
*
* @see ClassModel#interfaces()
* @see ClassBuilder#withInterfaces
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface Interfaces
extends ClassElement
permits InterfacesImpl {
/** {@return the interfaces of this class} */
/** {@return the interfaces of this class, may be empty} */
List<ClassEntry> interfaces();
/**
@@ -64,6 +70,7 @@ public sealed interface Interfaces
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
*/
static Interfaces ofSymbols(List<ClassDesc> interfaces) {
return of(Util.entryList(interfaces));
@@ -72,6 +79,7 @@ public sealed interface Interfaces
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
*/
static Interfaces ofSymbols(ClassDesc... interfaces) {
return ofSymbols(Arrays.asList(interfaces));

View File

@@ -24,21 +24,60 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.LabelTarget;
import java.util.ListIterator;
import jdk.internal.classfile.impl.LabelImpl;
/**
* A marker for a position within the instructions of a method body. The
* association between a label's identity and the position it represents is
* managed by the entity managing the method body (a {@link CodeModel} or {@link
* CodeBuilder}), not the label itself; this allows the same label to have a
* meaning both in an existing method (as managed by a {@linkplain CodeModel})
* and in the transformation of that method (as managed by a {@linkplain
* CodeBuilder}), while corresponding to different positions in each. When
* traversing the elements of a {@linkplain CodeModel}, {@linkplain Label}
* markers will be delivered at the position to which they correspond. A label
* can be bound to the current position within a {@linkplain CodeBuilder} via
* {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}.
* position is a cursor position in the list of instructions, similar to that
* of a {@link ListIterator}.
*
* <h2 id="reading">Reading Labels</h2>
* Labels read from {@code class} files represent positions in the {@code code}
* array of a {@link CodeAttribute Code} attribute. It is associated with a
* <dfn>{@index bci}</dfn> (bytecode index), also known as <dfn>{@index pc}</dfn>
* (program counter), the index into the {@code code} array; the actual cursor
* position is immediately before the given index, so a label at the beginning
* of the instructions has bci {@code 0}, and a label at the end of the
* instructions has bci {@link CodeAttribute#codeLength codeLength() + 1}. The
* bci can be inspected through {@link CodeAttribute#labelToBci
* CodeAttribute::labelToBci}.
* <p>
* In generic {@link CodeModel}s, a label may not have a bci value; the position
* of a label can be found by searching for the corresponding {@link LabelTarget}
* within that model.
*
* <h2 id="writing">Writing Labels</h2>
* Many models in {@link java.lang.classfile} refer to labels. To write a
* label, a label must be obtained, it must be bound to a {@link CodeBuilder}.
* <p>
* To obtain a label:
* <ul>
* <li>Use a label read from other models.
* <li>Use pre-defined labels from a {@link CodeBuilder}, such as {@link
* CodeBuilder#startLabel() CodeBuilder::startLabel}, {@link CodeBuilder#endLabel
* CodeBuilder::endLabel}, or {@link CodeBuilder.BlockCodeBuilder#breakLabel
* BlockCodeBuilder::breakLabel}. They are already bound.
* <li>Create labels with {@link CodeBuilder#newLabel CodeBuilder::newLabel} or
* {@link CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel}.
* </ul>
* <p>
* A label must be bound exactly once in the {@code CodeBuilder} where it is
* used; otherwise, writing fails. To bind an unbound label:
* <ul>
* <li>Send a read {@link LabelTarget} to a {@code CodeBuilder}.
* <li>Use {@link CodeBuilder#labelBinding CodeBuilder::labelBinding}.
* </ul>
* Note that a label read from another model is not automatically bound in a
* {@code CodeBuilder}; they are separate entities and the label is bound to
* different positions in them.
*
* @see CodeAttribute#labelToBci CodeAttribute::labelToBci
* @see CodeBuilder#newLabel CodeBuilder::newLabel
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
* @since 24
*/
public sealed interface Label

View File

@@ -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,7 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.function.Consumer;
@@ -34,14 +34,18 @@ import jdk.internal.classfile.impl.ChainedMethodBuilder;
import jdk.internal.classfile.impl.TerminalMethodBuilder;
/**
* A builder for methods. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withMethod(Utf8Entry, Utf8Entry, int, Consumer)}
* or to method transforms. The elements of a method can be specified
* abstractly (by passing a {@link MethodElement} to {@link #with(ClassFileElement)}
* or concretely by calling the various {@code withXxx} methods.
* A builder for methods. The main way to obtain a method builder is via {@link
* ClassBuilder#withMethod(String, MethodTypeDesc, int, Consumer)}. {@link
* ClassBuilder#withMethodBody(String, MethodTypeDesc, int, Consumer)} is
* useful if no attribute on the method except {@link CodeModel Code} needs to
* be configured, skipping the method handler.
* <p>
* Refer to {@link ClassFileBuilder} for general guidance and caution around
* the use of builders for structures in the {@code class} file format.
*
* @see MethodModel
* @see MethodTransform
*
* @jvms 4.6 Methods
* @since 24
*/
public sealed interface MethodBuilder
@@ -49,18 +53,30 @@ public sealed interface MethodBuilder
permits ChainedMethodBuilder, TerminalMethodBuilder {
/**
* Sets the method access flags.
* Sets the method access flags. The {@link AccessFlag#STATIC} flag cannot
* be modified after the builder is created.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @throws IllegalArgumentException if the {@link ClassFile#ACC_STATIC
* ACC_STATIC} flag is modified
* @see AccessFlags
* @see AccessFlag.Location#METHOD
*/
default MethodBuilder withFlags(int flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.METHOD, flags));
}
/**
* Sets the method access flags.
* Sets the method access flags. The {@link AccessFlag#STATIC} flag cannot
* be modified after the builder is created.
*
* @param flags the access flags, as a bit mask
* @return this builder
* @throws IllegalArgumentException if the {@link ClassFile#ACC_STATIC
* ACC_STATIC} flag is modified
* @see AccessFlags
* @see AccessFlag.Location#METHOD
*/
default MethodBuilder withFlags(AccessFlag... flags) {
return with(new AccessFlagsImpl(AccessFlag.Location.METHOD, flags));
@@ -68,24 +84,26 @@ public sealed interface MethodBuilder
/**
* Build the method body for this method.
*
* @param code a handler receiving a {@link CodeBuilder}
* @return this builder
* @see CodeModel
*/
MethodBuilder withCode(Consumer<? super CodeBuilder> code);
/**
* Build the method body for this method by transforming the body of another
* method.
*
* @implNote
* <p>This method behaves as if:
* <p>
* This method behaves as if:
* {@snippet lang=java :
* withCode(b -> b.transformCode(code, transform));
* withCode(cob -> cob.transform(code, transform));
* }
*
* @param code the method body to be transformed
* @param transform the transform to apply to the method body
* @return this builder
* @see CodeTransform
*/
MethodBuilder transformCode(CodeModel code, CodeTransform transform);
}

View File

@@ -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,9 +27,18 @@ package java.lang.classfile;
import java.lang.classfile.attribute.*;
/**
* A marker interface for elements that can appear when traversing
* a {@link MethodModel} or be presented to a {@link MethodBuilder}.
* Marker interface for a member element of a {@link MethodModel}. Such an
* element can appear when traversing a {@link MethodModel} unless otherwise
* specified, be supplied to a {@link MethodBuilder}, and be processed by a
* {@link MethodTransform}.
* <p>
* {@link AccessFlags} is the only member element of a method that appear
* exactly once during the traversal of a {@link MethodModel}.
*
* @see ClassFileElement##membership Membership Elements
* @see ClassElement
* @see FieldElement
* @see CodeElement
* @sealedGraph
* @since 24
*/

View File

@@ -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,24 +27,43 @@ package java.lang.classfile;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.BufferedMethodBuilder;
import jdk.internal.classfile.impl.MethodImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models a method. The contents of the method can be traversed via
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
* Models a method. A method can be viewed as a {@linkplain CompoundElement
* composition} of {@link MethodElement}s, or by random access via accessor
* methods if only specific parts of the method is needed.
* <p>
* Methods can be obtained from {@link ClassModel#methods()}, or in the
* traversal of member elements of a class.
* <p>
* {@link ClassBuilder#withMethod(String, MethodTypeDesc, int, Consumer)} is the
* main way to construct methods. {@link ClassBuilder#transformMethod} allows
* creating a new method by selectively processing the original method elements
* and directing the results to a method builder.
* <p>
* All method attributes are accessible as member elements.
*
* @see ClassModel#methods()
* @see MethodTransform
* @jvms 4.6 Methods
* @since 24
*/
public sealed interface MethodModel
extends CompoundElement<MethodElement>, AttributedElement, ClassElement
permits BufferedMethodBuilder.Model, MethodImpl {
/** {@return the access flags} */
/**
* {@return the access flags}
*
* @see AccessFlag.Location#METHOD
*/
AccessFlags flags();
/** {@return the class model this method is a member of, if known} */
@@ -53,10 +72,10 @@ public sealed interface MethodModel
/** {@return the name of this method} */
Utf8Entry methodName();
/** {@return the method descriptor of this method} */
/** {@return the method descriptor string of this method} */
Utf8Entry methodType();
/** {@return the method descriptor of this method, as a symbolic descriptor} */
/** {@return the method type, as a symbolic descriptor} */
default MethodTypeDesc methodTypeSymbol() {
return Util.methodTypeSymbol(methodType());
}

View File

@@ -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,7 +24,10 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.SignatureAttribute;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.List;
import jdk.internal.classfile.impl.SignaturesImpl;
@@ -33,34 +36,68 @@ import jdk.internal.classfile.impl.Util;
import static java.util.Objects.requireNonNull;
/**
* Models the generic signature of a method, as defined by JVMS {@jvms 4.7.9}.
* Models the generic signature of a method or constructor, as defined by JVMS
* {@jvms 4.7.9.1}.
*
* @see Executable
* @see SignatureAttribute
* @jls 8.4 Method Declarations
* @jls 8.8 Constructor Declarations
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface MethodSignature
permits SignaturesImpl.MethodSignatureImpl {
/** {@return the type parameters of this method} */
/**
* {@return the type parameters of this method or constructor, may be empty}
*
* @see Executable#getTypeParameters()
* @jls 8.4.4 Generic Methods
* @jls 8.8.4 Generic Constructors
*/
List<Signature.TypeParam> typeParameters();
/** {@return the signatures of the parameters of this method} */
/**
* {@return the signatures of the parameters of this method or constructor,
* may be empty} The parameters may differ from those in the method
* descriptor because some synthetic or implicit parameters are omitted.
*
* @see Executable#getGenericParameterTypes()
* @jls 8.4.1 Formal Parameters
* @jls 8.8.1 Formal Parameters
*/
List<Signature> arguments();
/** {@return the signatures of the return value of this method} */
/**
* {@return the signatures of the return value of this method} For
* constructors, this returns a signature representing {@code void}.
*
* @see Method#getGenericReturnType()
* @jls 8.4.5 Method Result
*/
Signature result();
/** {@return the signatures of the exceptions thrown by this method} */
/**
* {@return the signatures of the exceptions thrown by this method or
* constructor}
*
* @see Executable#getGenericExceptionTypes()
* @jls 8.4.6 Method Throws
* @jls 8.8.5 Constructor Throws
*/
List<Signature.ThrowableSig> throwableSignatures();
/** {@return the raw signature string} */
String signatureString();
/**
* {@return a method signature for a raw (no generic information) method descriptor}
* {@return a method signature for a raw method descriptor} The resulting
* signature has no type parameter or exception type declared.
*
* @param methodDescriptor the method descriptor
*/
public static MethodSignature of(MethodTypeDesc methodDescriptor) {
requireNonNull(methodDescriptor);
return new SignaturesImpl.MethodSignatureImpl(
List.of(),
@@ -70,13 +107,15 @@ public sealed interface MethodSignature
}
/**
* {@return a method signature}
* {@return a method signature with no type parameter or exception type}
* The parameters may differ from those in the method descriptor because
* some synthetic or implicit parameters are omitted.
*
* @param result signature for the return type
* @param arguments signatures for the method arguments
* @param arguments signatures for the method parameters
*/
public static MethodSignature of(Signature result,
Signature... arguments) {
return new SignaturesImpl.MethodSignatureImpl(List.of(),
List.of(),
requireNonNull(result),
@@ -84,17 +123,19 @@ public sealed interface MethodSignature
}
/**
* {@return a method signature}
* {@return a method signature} The parameters may differ from those in
* the method descriptor because some synthetic or implicit parameters are
* omitted.
*
* @param typeParameters signatures for the type parameters
* @param exceptions signatures for the exceptions
* @param result signature for the return type
* @param arguments signatures for the method arguments
* @param arguments signatures for the method parameters
*/
public static MethodSignature of(List<Signature.TypeParam> typeParameters,
List<Signature.ThrowableSig> exceptions,
Signature result,
Signature... arguments) {
return new SignaturesImpl.MethodSignatureImpl(
List.copyOf(requireNonNull(typeParameters)),
List.copyOf(requireNonNull(exceptions)),
@@ -103,12 +144,14 @@ public sealed interface MethodSignature
}
/**
* Parses a raw method signature string into a {@linkplain MethodSignature}
* Parses a raw method signature string into a {@code MethodSignature}.
*
* @param methodSignature the raw method signature string
* @return method signature
* @return the parsed method signature
* @throws IllegalArgumentException if the string is not a valid method
* signature string
*/
public static MethodSignature parseFrom(String methodSignature) {
return new SignaturesImpl(methodSignature).parseMethodSignature();
}
}

View File

@@ -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
@@ -34,9 +34,17 @@ import static java.util.Objects.requireNonNull;
/**
* A transformation on streams of {@link MethodElement}.
* <p>
* Refer to {@link ClassFileTransform} for general guidance and caution around
* the use of transforms for structures in the {@code class} file format.
* <p>
* A method transform can be lifted to a class transform via {@link
* ClassTransform#transformingMethods(MethodTransform)}, transforming only
* the {@link MethodModel} among the class members and passing all other
* elements to the builders.
*
* @see ClassFileTransform
*
* @see MethodModel
* @see ClassBuilder#transformMethod
* @since 24
*/
@FunctionalInterface
@@ -44,7 +52,7 @@ public non-sealed interface MethodTransform
extends ClassFileTransform<MethodTransform, MethodElement, MethodBuilder> {
/**
* A method transform that sends all elements to the builder.
* A method transform that passes all elements to the builder.
*/
MethodTransform ACCEPT_ALL = new MethodTransform() {
@Override
@@ -54,7 +62,7 @@ public non-sealed interface MethodTransform
};
/**
* Create a stateful method transform from a {@link Supplier}. The supplier
* Creates a stateful method transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
@@ -67,7 +75,7 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that passes each element through to the builder,
* Creates a method transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
@@ -89,7 +97,7 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that passes each element through to the builder,
* Creates a method transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop
@@ -104,8 +112,9 @@ public non-sealed interface MethodTransform
}
/**
* Create a method transform that transforms {@link CodeModel} elements
* with the supplied code transform.
* Creates a method transform that transforms {@link CodeModel} elements
* with the supplied code transform, passing every other element through to
* the builder.
*
* @param xform the method transform
* @return the class transform

File diff suppressed because it is too large Load Diff

View File

@@ -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
@@ -35,13 +35,16 @@ import java.lang.classfile.instruction.LocalVariableType;
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
/**
* Models metadata about a {@link CodeAttribute}, such as entries in the
* exception table, line number table, local variable table, or the mapping
* between instructions and labels. Pseudo-instructions are delivered as part
* of the element stream of a {@link CodeModel}. Delivery of some
* pseudo-instructions can be disabled by modifying the value of classfile
* options (e.g., {@link ClassFile.DebugElementsOption}).
* Models metadata about a {@link CodeModel}, derived from the {@link
* CodeAttribute Code} attribute itself or its attributes.
* <p>
* Order is significant for some pseudo-instructions relative to {@link
* Instruction}s, such as {@link LabelTarget} or {@link LineNumber}. Some
* pseudo-instructions can be omitted in reading and writing according to
* certain {@link ClassFile.Option}s. These are specified in the corresponding
* modeling interfaces.
*
* @sealedGraph
* @since 24
*/
public sealed interface PseudoInstruction

View File

@@ -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,7 +24,15 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.SignatureAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.constant.ClassDesc;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.List;
import java.util.Optional;
@@ -36,6 +44,10 @@ import static java.util.Objects.requireNonNull;
/**
* Models generic Java type signatures, as defined in JVMS {@jvms 4.7.9.1}.
*
* @see Type
* @see SignatureAttribute
* @jls 4.1 The Kinds of Types and Values
* @jvms 4.7.9.1 Signatures
* @sealedGraph
* @since 24
*/
@@ -45,16 +57,21 @@ public sealed interface Signature {
String signatureString();
/**
* Parses generic Java type signature from raw string
* Parses a Java type signature from a raw string.
*
* @param javaTypeSignature raw Java type signature string
* @return Java type signature
* @return a Java type signature
* @throws IllegalArgumentException if the string is not a valid Java type
* signature string
*/
public static Signature parseFrom(String javaTypeSignature) {
return new SignaturesImpl(javaTypeSignature).parseSignature();
}
/**
* {@return a Java type signature}
* {@return a Java type signature from a field descriptor} The returned
* signature represents a reifiable type (JLS {@jls 4.7}).
*
* @param classDesc the symbolic description of the Java type
*/
public static Signature of(ClassDesc classDesc) {
@@ -67,8 +84,10 @@ public sealed interface Signature {
}
/**
* Models the signature of a primitive type or void
* Models the signature of a primitive type (JLS {@jls 4.2}) or void.
*
* @jls 4.2 Primitive Types and Values
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface BaseTypeSig extends Signature
@@ -81,6 +100,8 @@ public sealed interface Signature {
* {@return the signature of a primitive type or void}
* @param classDesc a symbolic descriptor for the base type, must correspond
* to a primitive type
* @throws IllegalArgumentException if the {@code classDesc} is not
* primitive
*/
public static BaseTypeSig of(ClassDesc classDesc) {
requireNonNull(classDesc);
@@ -92,6 +113,8 @@ public sealed interface Signature {
/**
* {@return the signature of a primitive type or void}
* @param baseType the single-letter descriptor for the base type
* @throws IllegalArgumentException if the {@code baseType} is not a
* valid descriptor character for a primitive type or void
*/
public static BaseTypeSig of(char baseType) {
if ("VIJCSBFDZ".indexOf(baseType) < 0)
@@ -104,6 +127,8 @@ public sealed interface Signature {
* Models the signature of a reference type, which may be a class, interface,
* type variable, or array type.
*
* @jls 4.3 Reference Types and Values
* @jvms 4.7.9.1 Signatures
* @sealedGraph
* @since 24
*/
@@ -115,42 +140,68 @@ public sealed interface Signature {
/**
* Models the signature of a possibly-parameterized class or interface type.
*
* @see Type
* @see ParameterizedType
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface ClassTypeSig
extends RefTypeSig, ThrowableSig
permits SignaturesImpl.ClassTypeSigImpl {
/** {@return the signature of the outer type, if any} */
/**
* {@return the signature of the class that this class is a member of,
* only if this is a member class} Note that the outer class may be
* absent if it is not a parameterized type.
*
* @jls 4.5 Parameterized Types
*/
Optional<ClassTypeSig> outerType();
/** {@return the class name} */
/**
* {@return the class or interface name; includes the {@linkplain
* ClassEntry##internalname slash-separated} package name if there is no
* outer type}
*/
String className();
/** {@return the class name, as a symbolic descriptor} */
/**
* {@return this class or interface, as a symbolic descriptor}
*/
default ClassDesc classDesc() {
var outer = outerType();
return outer.isEmpty() ? ClassDesc.ofInternalName(className())
: outer.get().classDesc().nested(className());
}
/** {@return the type arguments of the class} */
/**
* {@return the type arguments of this class or interface}
* Note that the outer type may have more type arguments.
*
* @jls 4.5 Parameterized Types
*/
List<TypeArg> typeArgs();
/**
* {@return a class type signature}
* @param className the name of the class
* @param typeArgs signatures of the type arguments
* {@return a class or interface signature without an outer type}
*
* @param className the name of the class or interface
* @param typeArgs the type arguments
* @throws IllegalArgumentException if {@code className} does not
* represent a class or interface
*/
public static ClassTypeSig of(ClassDesc className, TypeArg... typeArgs) {
return of(null, className, typeArgs);
}
/**
* {@return a class type signature for an inner class}
* @param outerType signature of the outer type
* @param className the name of the class
* @param typeArgs signatures of the type arguments
* {@return a class or interface signature}
*
* @param outerType signature of the outer type, may be {@code null}
* @param className the name of this class or interface
* @param typeArgs the type arguments
* @throws IllegalArgumentException if {@code className} does not
* represent a class or interface
*/
public static ClassTypeSig of(ClassTypeSig outerType, ClassDesc className, TypeArg... typeArgs) {
requireNonNull(className);
@@ -158,19 +209,21 @@ public sealed interface Signature {
}
/**
* {@return a class type signature}
* @param className the name of the class
* @param typeArgs signatures of the type arguments
* {@return a class or interface signature without an outer type}
*
* @param className the name of the class or interface
* @param typeArgs the type arguments
*/
public static ClassTypeSig of(String className, TypeArg... typeArgs) {
return of(null, className, typeArgs);
}
/**
* {@return a class type signature for an inner class}
* @param outerType signature of the outer type
* @param className the name of the class
* @param typeArgs signatures of the type arguments
* {@return a class type signature}
*
* @param outerType signature of the outer type, may be {@code null}
* @param className the name of this class or interface
* @param typeArgs the type arguments
*/
public static ClassTypeSig of(ClassTypeSig outerType, String className, TypeArg... typeArgs) {
requireNonNull(className);
@@ -179,15 +232,25 @@ public sealed interface Signature {
}
/**
* Models the type argument.
* Models a type argument, an argument to a type parameter.
*
* @see Type
* @see WildcardType
* @jls 4.5.1 Type Arguments of Parameterized Types
* @jvms 4.7.9.1 Signatures
* @sealedGraph
* @since 24
*/
public sealed interface TypeArg {
/**
* Models an unbounded type argument {@code *}.
* Models an unbounded wildcard type argument {@code *}, or {@code
* ?} in Java programs. This type argument has an implicit upper
* bound of {@link Object}.
*
* @see WildcardType#getUpperBounds()
* @jls 4.5.1 Type Arguments of Parameterized Types
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface Unbounded extends TypeArg permits SignaturesImpl.UnboundedTypeArgImpl {
@@ -195,31 +258,46 @@ public sealed interface Signature {
/**
* Models a type argument with an explicit bound type.
*
* @jls 4.5.1 Type Arguments of Parameterized Types
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface Bounded extends TypeArg permits SignaturesImpl.TypeArgImpl {
/**
* Models a type argument's wildcard indicator.
*
* @jls 4.5.1 Type Arguments of Parameterized Types
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public enum WildcardIndicator {
/**
* No wildcard (empty), an exact type. Also known as
* {@index invariant}.
* No wildcard (empty), an exact type. Also known as
* {@index invariant}. This is the direct use of a
* reference type in Java programs.
*
* @see Type
*/
NONE,
/**
* Upper-bound indicator {@code +}. Also known as
* {@index covariant}.
* Upper-bound indicator {@code +}. Also known as
* {@index covariant}. This is the {@code ? extends}
* prefix in Java programs.
*
* @see WildcardType#getUpperBounds()
*/
EXTENDS,
/**
* Lower-bound indicator {@code -}. Also known as
* {@index contravariant}.
* Lower-bound indicator {@code -}. Also known as
* {@index contravariant}. This is the {@code ? super}
* prefix in Java programs.
*
* @see WildcardType#getLowerBounds()
*/
SUPER;
}
@@ -232,8 +310,10 @@ public sealed interface Signature {
}
/**
* {@return a bounded type arg}
* @param boundType the bound
* {@return a type argument of a reference type}
*
* @param boundType the reference type
* @see Bounded.WildcardIndicator#NONE
*/
public static TypeArg.Bounded of(RefTypeSig boundType) {
requireNonNull(boundType);
@@ -241,15 +321,17 @@ public sealed interface Signature {
}
/**
* {@return an unbounded type arg}
* {@return an unbounded wildcard type argument {@code *}}
*/
public static TypeArg.Unbounded unbounded() {
return SignaturesImpl.UnboundedTypeArgImpl.INSTANCE;
}
/**
* {@return an upper-bounded type arg}
* {@return an upper-bounded wildcard type argument}
*
* @param boundType the upper bound
* @see Bounded.WildcardIndicator#EXTENDS
*/
public static TypeArg.Bounded extendsOf(RefTypeSig boundType) {
requireNonNull(boundType);
@@ -257,8 +339,10 @@ public sealed interface Signature {
}
/**
* {@return a lower-bounded type arg}
* {@return a lower-bounded wildcard type argument}
*
* @param boundType the lower bound
* @see Bounded.WildcardIndicator#SUPER
*/
public static TypeArg.Bounded superOf(RefTypeSig boundType) {
requireNonNull(boundType);
@@ -266,9 +350,10 @@ public sealed interface Signature {
}
/**
* {@return a bounded type arg}
* @param wildcard the wild card
* @param boundType optional bound type
* {@return a bounded type argument}
*
* @param wildcard the wildcard indicator
* @param boundType the bound type
*/
public static TypeArg.Bounded bounded(Bounded.WildcardIndicator wildcard, RefTypeSig boundType) {
requireNonNull(wildcard);
@@ -278,8 +363,13 @@ public sealed interface Signature {
}
/**
* Models the signature of a type variable.
* Models the signature of a type variable. A type variable is introduced
* by a {@linkplain TypeParam type parameter} declaration.
*
* @see TypeVariable
* @see TypeParam
* @jls 4.4 Type Variables
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface TypeVarSig
@@ -291,6 +381,7 @@ public sealed interface Signature {
/**
* {@return a signature for a type variable}
*
* @param identifier the name of the type variable
*/
public static TypeVarSig of(String identifier) {
@@ -301,6 +392,10 @@ public sealed interface Signature {
/**
* Models the signature of an array type.
*
* @see Type
* @see GenericArrayType
* @jls 10.1 Array Types
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface ArrayTypeSig
@@ -311,7 +406,7 @@ public sealed interface Signature {
Signature componentSignature();
/**
* {@return a signature for an array type}
* {@return an array type with the given component type}
* @param componentSignature the component type
*/
public static ArrayTypeSig of(Signature componentSignature) {
@@ -322,6 +417,8 @@ public sealed interface Signature {
* {@return a signature for an array type}
* @param dims the dimension of the array
* @param componentSignature the component type
* @throws IllegalArgumentException if the resulting array type exceeds
* 255 dimensions
*/
public static ArrayTypeSig of(int dims, Signature componentSignature) {
requireNonNull(componentSignature);
@@ -334,8 +431,15 @@ public sealed interface Signature {
}
/**
* Models a signature for a type parameter of a generic class or method.
* Models a signature for a type parameter of a generic class, interface,
* method, or constructor, which introduces a {@linkplain TypeVarSig type
* variable}.
*
* @see GenericDeclaration#getTypeParameters()
* @see TypeVariable
* @see TypeVarSig
* @jls 4.4 Type Variables
* @jvms 4.7.9.1 Signatures
* @since 24
*/
public sealed interface TypeParam
@@ -344,16 +448,23 @@ public sealed interface Signature {
/** {@return the name of the type parameter} */
String identifier();
/** {@return the class bound of the type parameter} */
/**
* {@return the class bound of the type parameter} This may be empty
* if this type parameter only has interface bounds.
*/
Optional<RefTypeSig> classBound();
/** {@return the interface bounds of the type parameter} */
/**
* {@return the interface bounds of the type parameter} This may be
* empty.
*/
List<RefTypeSig> interfaceBounds();
/**
* {@return a signature for a type parameter}
*
* @param identifier the name of the type parameter
* @param classBound the class bound of the type parameter
* @param classBound the class bound of the type parameter, may be {@code null}
* @param interfaceBounds the interface bounds of the type parameter
*/
public static TypeParam of(String identifier, RefTypeSig classBound, RefTypeSig... interfaceBounds) {
@@ -365,8 +476,9 @@ public sealed interface Signature {
/**
* {@return a signature for a type parameter}
*
* @param identifier the name of the type parameter
* @param classBound the class bound of the type parameter
* @param classBound the optional class bound of the type parameter
* @param interfaceBounds the interface bounds of the type parameter
*/
public static TypeParam of(String identifier, Optional<RefTypeSig> classBound, RefTypeSig... interfaceBounds) {
@@ -378,8 +490,10 @@ public sealed interface Signature {
}
/**
* Models a signature for a throwable type.
* Marker interface for a signature for a throwable type.
*
* @jls 8.4.6 Method Throws
* @jvms 4.7.9.1 Signatures
* @sealedGraph
* @since 24
*/

View File

@@ -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,13 +25,24 @@
package java.lang.classfile;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.impl.SuperclassImpl;
/**
* Models the superclass of a class. Delivered as a {@link
* java.lang.classfile.ClassElement} when traversing a {@link ClassModel}.
* Models the superclass (JVMS {@jvms 4.1}) of a class. A {@code Superclass}
* appears at most once in a {@link ClassModel}: it must be absent for
* {@linkplain ClassModel#isModuleInfo() module descriptors} or the {@link
* Object} class, and must be present otherwise. A {@link ClassBuilder} sets
* the {@link Object} class as the superclass if the superclass is not supplied
* and the class to build is required to have a superclass.
* <p>
* All {@linkplain ClassFile#ACC_INTERFACE interfaces} have {@link Object} as
* their superclass.
*
* @see ClassModel#superclass()
* @see ClassBuilder#withSuperclass
* @jvms 4.1 The {@code ClassFile} Structure
* @since 24
*/
public sealed interface Superclass
@@ -43,6 +54,7 @@ public sealed interface Superclass
/**
* {@return a {@linkplain Superclass} element}
*
* @param superclassEntry the superclass
*/
static Superclass of(ClassEntry superclassEntry) {

View File

@@ -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
@@ -59,6 +59,7 @@ public sealed interface TypeAnnotation
/**
* The kind of target on which the annotation appears, as defined in JVMS {@jvms 4.7.20.1}.
*
* @see TargetInfo#targetType()
* @since 24
*/
public enum TargetType {
@@ -189,6 +190,7 @@ public sealed interface TypeAnnotation
/**
* Specifies which type in a declaration or expression is being annotated.
*
* @see #targetInfo()
* @sealedGraph
* @since 24
*/
@@ -440,8 +442,11 @@ public sealed interface TypeAnnotation
}
/**
* {@return a target for annotations on the type in a formal parameter declaration of a method,
* constructor, or lambda expression}
* {@return a target for annotations on the type in a formal parameter
* declaration of a method, constructor, or lambda expression} The
* index may differ from the index in the method descriptor because some
* synthetic or implicit parameters are omitted.
*
* @param formalParameterIndex specifies which formal parameter declaration has an annotated type
*/
static FormalParameterTarget ofMethodFormalParameter(int formalParameterIndex) {
@@ -498,7 +503,7 @@ public sealed interface TypeAnnotation
* @param targetType {@link TargetType#INSTANCEOF}, {@link TargetType#NEW},
* {@link TargetType#CONSTRUCTOR_REFERENCE},
* or {@link TargetType#METHOD_REFERENCE}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
*/
static OffsetTarget ofOffset(TargetType targetType, Label target) {
return new TargetInfoImpl.OffsetTargetImpl(targetType, target);
@@ -506,7 +511,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the type in an instanceof expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
*/
static OffsetTarget ofInstanceofExpr(Label target) {
return ofOffset(TargetType.INSTANCEOF, target);
@@ -514,7 +519,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the type in a new expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
*/
static OffsetTarget ofNewExpr(Label target) {
return ofOffset(TargetType.NEW, target);
@@ -522,7 +527,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the type before the :: in a constructor reference expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
*/
static OffsetTarget ofConstructorReference(Label target) {
return ofOffset(TargetType.CONSTRUCTOR_REFERENCE, target);
@@ -530,7 +535,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the type before the :: in a method reference expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
*/
static OffsetTarget ofMethodReference(Label target) {
return ofOffset(TargetType.METHOD_REFERENCE, target);
@@ -545,7 +550,7 @@ public sealed interface TypeAnnotation
* {@link TargetType#METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link TargetType#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT},
* or {@link TargetType#METHOD_REFERENCE_TYPE_ARGUMENT}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the cast operator or argument is annotated
*/
static TypeArgumentTarget ofTypeArgument(TargetType targetType, Label target, int typeArgumentIndex) {
@@ -554,7 +559,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the i'th type in a cast expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the cast operator is annotated
*/
static TypeArgumentTarget ofCastExpr(Label target, int typeArgumentIndex) {
@@ -564,7 +569,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* an explicit constructor invocation statement}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofConstructorInvocationTypeArgument(Label target, int typeArgumentIndex) {
@@ -574,7 +579,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a method invocation expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofMethodInvocationTypeArgument(Label target, int typeArgumentIndex) {
@@ -584,7 +589,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a new expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofConstructorReferenceTypeArgument(Label target, int typeArgumentIndex) {
@@ -594,7 +599,7 @@ public sealed interface TypeAnnotation
/**
* {@return a target for annotations on the i'th type argument in the explicit type argument list for
* a method reference expression}
* @param target the code label corresponding to the instruction
* @param target the label right before the instruction
* @param typeArgumentIndex specifies which type in the argument is annotated
*/
static TypeArgumentTarget ofMethodReferenceTypeArgument(Label target, int typeArgumentIndex) {
@@ -607,6 +612,9 @@ public sealed interface TypeAnnotation
* parameter of a generic class, generic interface, generic method, or
* generic constructor.
*
* @see #ofTypeParameter(TargetType, int)
* @see #ofClassTypeParameter(int)
* @see #ofMethodTypeParameter(int)
* @since 24
*/
sealed interface TypeParameterTarget extends TargetInfo
@@ -625,6 +633,7 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on a type in the extends or implements
* clause of a class or interface declaration.
*
* @see #ofClassExtends(int)
* @since 24
*/
sealed interface SupertypeTarget extends TargetInfo
@@ -648,6 +657,9 @@ public sealed interface TypeAnnotation
* type parameter declaration of a generic class, interface, method, or
* constructor.
*
* @see #ofTypeParameterBound(TargetType, int, int)
* @see #ofClassTypeParameterBound(int, int)
* @see #ofMethodTypeParameterBound(int, int)
* @since 24
*/
sealed interface TypeParameterBoundTarget extends TargetInfo
@@ -673,6 +685,10 @@ public sealed interface TypeAnnotation
* declaration, the return type of a method, the type of a newly constructed
* object, or the receiver type of a method or constructor.
*
* @see #of(TargetType)
* @see #ofField()
* @see #ofMethodReturn()
* @see #ofMethodReceiver()
* @since 24
*/
sealed interface EmptyTarget extends TargetInfo
@@ -683,16 +699,17 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on the type in a formal parameter
* declaration of a method, constructor, or lambda expression.
*
* @see #ofMethodFormalParameter(int)
* @since 24
*/
sealed interface FormalParameterTarget extends TargetInfo
permits TargetInfoImpl.FormalParameterTargetImpl {
/**
* Which formal parameter declaration has an annotated type.
*
* @return the index into the formal parameter declarations, in the order
* declared in the source code
* {@return the index into the formal parameter declarations, in the
* order declared in the source code} The index may differ from the
* index in the method descriptor because some synthetic or implicit
* parameters are omitted.
*/
int formalParameterIndex();
}
@@ -701,6 +718,7 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on the i'th type in the throws
* clause of a method or constructor declaration.
*
* @see #ofThrows(int)
* @since 24
*/
sealed interface ThrowsTarget extends TargetInfo
@@ -720,13 +738,14 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on the type in a local variable declaration,
* including a variable declared as a resource in a try-with-resources statement.
*
* @see #ofLocalVariable(List)
* @since 24
*/
sealed interface LocalVarTarget extends TargetInfo
permits TargetInfoImpl.LocalVarTargetImpl {
/**
* {@return the table of local variable location/indices.}
* {@return the table of local variable location/indices}
*/
List<LocalVarTargetInfo> table();
}
@@ -736,6 +755,7 @@ public sealed interface TypeAnnotation
* has a value, and the index into the local variable array of the current
* frame at which that local variable can be found.
*
* @see LocalVarTarget
* @since 24
*/
sealed interface LocalVarTargetInfo
@@ -782,6 +802,7 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on the i'th type in an exception parameter
* declaration.
*
* @see #ofExceptionParameter(int)
* @since 24
*/
sealed interface CatchTarget extends TargetInfo
@@ -800,17 +821,22 @@ public sealed interface TypeAnnotation
* Indicates that an annotation appears on either the type in an instanceof expression
* or a new expression, or the type before the :: in a method reference expression.
*
* @see #ofOffset(TargetType, Label)
* @see #ofNewExpr(Label)
* @see #ofInstanceofExpr(Label)
* @see #ofConstructorReference(Label)
* @see #ofMethodReference(Label)
* @since 24
*/
sealed interface OffsetTarget extends TargetInfo
permits TargetInfoImpl.OffsetTargetImpl {
/**
* The code array offset of either the bytecode instruction
* corresponding to the instanceof expression, the new bytecode instruction corresponding to the new
* expression, or the bytecode instruction corresponding to the method reference expression.
* The label right before the {@link Instruction} corresponding to the
* instanceof expression, the new expression, or the method reference
* expression.
*
* @return the code label corresponding to the instruction
* @return the label right before the instruction
*/
Label target();
}
@@ -821,19 +847,24 @@ public sealed interface TypeAnnotation
* expression, an explicit constructor invocation statement, a method invocation expression, or a method reference
* expression.
*
* @see #ofTypeArgument(TargetType, Label, int)
* @see #ofCastExpr(Label, int)
* @see #ofConstructorInvocationTypeArgument(Label, int)
* @see #ofConstructorReferenceTypeArgument(Label, int)
* @see #ofMethodInvocationTypeArgument(Label, int)
* @see #ofMethodReferenceTypeArgument(Label, int)
* @since 24
*/
sealed interface TypeArgumentTarget extends TargetInfo
permits TargetInfoImpl.TypeArgumentTargetImpl {
/**
* The code array offset of either the bytecode instruction
* corresponding to the cast expression, the new bytecode instruction corresponding to the new expression, the
* bytecode instruction corresponding to the explicit constructor invocation statement, the bytecode
* instruction corresponding to the method invocation expression, or the bytecode instruction corresponding to
* the method reference expression.
* The label right before the {@link Instruction} corresponding to the
* cast expression, the new expression, the explicit constructor
* invocation statement, the method invocation expression, or the method
* reference expression.
*
* @return the code label corresponding to the instruction
* @return the label right before the instruction
*/
Label target();
@@ -856,6 +887,7 @@ public sealed interface TypeAnnotation
* JVMS: Type_path structure identifies which part of the type is annotated,
* as defined in JVMS {@jvms 4.7.20.2}
*
* @see #targetPath()
* @since 24
*/
sealed interface TypePathComponent

View File

@@ -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,6 +26,9 @@
package java.lang.classfile;
import java.lang.classfile.instruction.DiscontinuedInstruction;
import java.lang.classfile.instruction.LoadInstruction;
import java.lang.classfile.instruction.NewPrimitiveArrayInstruction;
import java.lang.classfile.instruction.StoreInstruction;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.TypeDescriptor;
@@ -33,13 +36,17 @@ import java.lang.invoke.TypeDescriptor;
import jdk.internal.vm.annotation.Stable;
/**
* Describes the data types Java Virtual Machine operates on.
* This omits {@code returnAddress} (JVMS {@jvms 2.3.3}),
* which is only used by discontinued {@link
* DiscontinuedInstruction.JsrInstruction jsr} and {@link
* DiscontinuedInstruction.RetInstruction ret} instructions,
* and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which
* appears as a method return type.
* Describes the data types Java Virtual Machine operates on. This omits {@code
* returnAddress} (JVMS {@jvms 2.3.3}) and includes {@link #VOID void} (JVMS
* {@jvms 4.3.3}), which appears as a method return type.
* <p>
* The <code>{@index returnAddress}</code> type is only used by discontinued
* {@linkplain DiscontinuedInstruction.JsrInstruction jump subroutine} and
* {@linkplain DiscontinuedInstruction.RetInstruction return from subroutine}
* instructions. Jump subroutine instructions push {@code returnAddress} to the
* operand stack; {@link StoreInstruction astore} instructions store {@code
* returnAddress} from the operand stack to local variables; return from
* subroutine instructions load {@code returnAddress} from local variables.
*
* <h2 id="computational-type">Computational Type</h2>
* In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}),
@@ -101,11 +108,16 @@ public enum TypeKind {
*/
LONG(2, 11),
/**
* The primitive type {@code float}.
* The primitive type {@code float}. All NaN values of {@code float} may or
* may not be collapsed into a single {@linkplain Float#NaN "canonical" NaN
* value} in loading and storing.
*/
FLOAT(1, 6),
/**
* The primitive type {@code double}. It is of {@linkplain #slotSize() category} 2.
* The primitive type {@code double}. It is of {@linkplain #slotSize()
* category} 2. All NaN values of {@code double} may or may not be
* collapsed into a single {@linkplain Double#NaN "canonical" NaN value}
* in loading and storing.
*/
DOUBLE(2, 7),
// End primitive types
@@ -164,7 +176,10 @@ public enum TypeKind {
/**
* {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array
* of this component type, or {@code -1} if this type is not supported by {@code newarray}}
* @jvms 6.5.newarray <i>newarray</i>
*
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #fromNewarrayCode(int) fromNewarrayCode(int)
*/
public int newarrayCode() {
return newarrayCode;
@@ -175,6 +190,7 @@ public enum TypeKind {
* This is also the category of this type for instructions operating on the operand stack without
* regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2
* pop2}.
*
* @jvms 2.6.1 Local Variables
* @jvms 2.6.2 Operand Stacks
*/
@@ -185,6 +201,9 @@ public enum TypeKind {
/**
* {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void}
* for {@code void}}
*
* @see LoadInstruction
* @see StoreInstruction
*/
public TypeKind asLoadable() {
return ordinal() < 4 ? INT : this;
@@ -193,9 +212,12 @@ public enum TypeKind {
/**
* {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY
* newarray}}
*
* @param newarrayCode the operand of the {@code newarray} instruction
* @throws IllegalArgumentException if the code is invalid
* @jvms 6.5.newarray <i>newarray</i>
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #newarrayCode() newarrayCode()
*/
public static TypeKind fromNewarrayCode(int newarrayCode) {
return switch (newarrayCode) {

View File

@@ -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,24 +27,31 @@ package java.lang.classfile.attribute;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper;
import java.lang.classfile.AttributeMapper.AttributeStability;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.MethodElement;
import java.lang.classfile.MethodModel;
import java.lang.reflect.Method;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code AnnotationDefault} attribute (JVMS {@jvms 4.7.22}), which can
* appear on methods of annotation types, and records the default value
* {@jls 9.6.2} for the element corresponding to this method. Delivered as a
* {@link MethodElement} when traversing the elements of a {@link MethodModel}.
* Models the {@link Attributes#annotationDefault() AnnotationDefault} attribute
* (JVMS {@jvms 4.7.22}), which records the default value (JLS {@jls 9.6.2}) for
* the annotation interface element defined by this method.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
* This attribute only appears on methods, and does not permit {@linkplain
* AttributeMapper#allowMultiple multiple instances} in a method. It has a
* data dependency on the {@linkplain AttributeStability#CP_REFS constant pool}.
* <p>
* The attribute was introduced in the Java SE Platform version 5.0.
* This attribute was introduced in the Java SE Platform version 5.0, major
* version {@value ClassFile#JAVA_5_VERSION}.
*
* @see Attributes#annotationDefault()
* @jls 9.6.2 Defaults for Annotation Interface Elements
* @jvms 4.7.22 The {@code AnnotationDefault} Attribute
* @since 24
*/
public sealed interface AnnotationDefaultAttribute
@@ -53,14 +60,16 @@ public sealed interface AnnotationDefaultAttribute
UnboundAttribute.UnboundAnnotationDefaultAttribute {
/**
* {@return the default value of the annotation type element represented by
* this method}
* {@return the default value of the annotation interface element defined by
* the enclosing method}
*
* @see Method#getDefaultValue()
*/
AnnotationValue defaultValue();
/**
* {@return an {@code AnnotationDefault} attribute}
* @param annotationDefault the default value of the annotation type element
* @param annotationDefault the default value of the annotation interface element
*/
static AnnotationDefaultAttribute of(AnnotationValue annotationDefault) {
return new UnboundAttribute.UnboundAnnotationDefaultAttribute(annotationDefault);

View File

@@ -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,24 +26,41 @@
package java.lang.classfile.attribute;
import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper;
import java.lang.classfile.AttributeMapper.AttributeStability;
import java.lang.classfile.Attributes;
import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.util.List;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code BootstrapMethods} attribute (JVMS {@jvms 4.7.23}), which serves as
* an extension to the constant pool of a classfile. Elements of the bootstrap
* method table are accessed through {@link ConstantPool}.
* Models the {@link Attributes#bootstrapMethods() BootstrapMethods} attribute
* (JVMS {@jvms 4.7.23}), which stores symbolic information for the execution of
* bootstrap methods, used by dynamically-computed call sites and constants.
* It is logically a part of the constant pool of a {@code class} file and thus
* not delivered in {@link ClassModel} traversal; its elements are accessible
* through {@link ConstantPool}.
* <p>
* The attribute does not permit multiple instances in a given location.
* Subsequent occurrence of the attribute takes precedence during the attributed
* element build or transformation.
* This attribute only appears on classes, and does not permit {@linkplain
* AttributeMapper#allowMultiple multiple instances} in a class. It has a
* data dependency on the {@linkplain AttributeStability#CP_REFS constant pool}.
* <p>
* The attribute was introduced in the Java SE Platform version 7.
* This attribute cannot be constructed directly; its entries can be constructed
* through {@link ConstantPoolBuilder#bsmEntry}, resulting in at most one
* attribute instance in the built {@code class} file.
* <p>
* The attribute was introduced in the Java SE Platform version 7, major version
* {@value ClassFile#JAVA_7_VERSION}.
*
* @see Attributes#bootstrapMethods()
* @see java.lang.invoke##bsm Execution of bootstrap methods
* @jvms 4.7.23 The {@code BootstrapMethods} Attribute
* @since 24
*/
public sealed interface BootstrapMethodsAttribute
@@ -57,8 +74,7 @@ public sealed interface BootstrapMethodsAttribute
List<BootstrapMethodEntry> bootstrapMethods();
/**
* {@return the size of the bootstrap methods table}. Calling this method
* does not necessarily inflate the entire table.
* {@return the size of the bootstrap methods table}
*/
int bootstrapMethodsSize();

View File

@@ -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,64 +24,77 @@
*/
package java.lang.classfile.attribute;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.instruction.CharacterRange;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single character range in the {@link CharacterRangeTableAttribute}.
* Models a single character range entry in the {@link
* CharacterRangeTableAttribute}.
* <p>
* Each character range entry associates a range of indices in the code array
* with a range of character positions in the source file. A character position
* in the source file is represented by a line number and a column number, and
* its value is encoded as {@code lineNumber << 10 + columnNumber}. Note that
* column numbers are not the same as byte indices in a column as multibyte
* characters may be present in the source file.
*
* Each character range entry includes a
* flag which indicates what kind of range is described: statement, assignment,
* method call, etc.
*
* @see CharacterRangeTableAttribute#characterRangeTable()
* @see CharacterRange
* @since 24
*/
public sealed interface CharacterRangeInfo
permits UnboundAttribute.UnboundCharacterRangeInfo {
/**
* {@return the start of the character range region (inclusive)} This is
* the index into the code array at which the code for this character range
* begins.
* {@return the start of indices in the code array, inclusive}
*
* @see CharacterRange#startScope()
*/
int startPc();
/**
* {@return the end of the character range region (exclusive)} This is the
* index into the code array after which the code for this character range
* ends.
* {@return the end of indices in the code array, exclusive}
*
* @see CharacterRange#endScope()
*/
int endPc();
/**
* {@return the encoded start of the character range region (inclusive)}
* The value is constructed from the line_number/column_number pair as given
* by {@code line_number << 10 + column_number}, where the source file is
* viewed as an array of (possibly multi-byte) characters.
* {@return the encoded start of character positions in the source file,
* inclusive}
*/
int characterRangeStart();
/**
* {@return the encoded end of the character range region (exclusive)}.
* The value is constructed from the line_number/column_number pair as given
* by {@code line_number << 10 + column_number}, where the source file is
* viewed as an array of (possibly multi-byte) characters.
* {@return the encoded end of character positions in the source file,
* exclusive}
*/
int characterRangeEnd();
/**
* {@return the flags of this character range entry}
* <p>
* The value of the flags item describes the kind of range. Multiple flags
* may be set within flags.
* <ul>
* <li>{@link CharacterRange#FLAG_STATEMENT} Range is a Statement
* (except ExpressionStatement), StatementExpression {@jls 14.8}, as well as each
* VariableDeclaratorId = VariableInitializer of
* LocalVariableDeclarationStatement {@jls 14.4} or FieldDeclaration {@jls 8.3} in the
* grammar.
* <li>{@link CharacterRange#FLAG_BLOCK} Range is a Block in the
* grammar.
* (except ExpressionStatement), StatementExpression (JLS {@jls 14.8}), as
* well as each {@code VariableDeclaratorId = VariableInitializer} of
* LocalVariableDeclarationStatement (JLS {@jls 14.4}) or FieldDeclaration
* (JLS {@jls 8.3}) in the grammar.
* <li>{@link CharacterRange#FLAG_BLOCK} Range is a Block in the grammar.
* <li>{@link CharacterRange#FLAG_ASSIGNMENT} Range is an assignment
* expression - Expression1 AssignmentOperator Expression1 in the grammar as
* well as increment and decrement expressions (both prefix and postfix).
* expression - {@code Expression1 AssignmentOperator Expression1} in the
* grammar as well as increment and decrement expressions (both prefix and
* postfix).
* <li>{@link CharacterRange#FLAG_FLOW_CONTROLLER} An expression
* whose value will effect control flow. {@code Flowcon} in the following:
* whose value will affect control flow. {@code Flowcon} in the following:
* <pre>
* if ( Flowcon ) Statement [else Statement]
* for ( ForInitOpt ; [Flowcon] ; ForUpdateOpt ) Statement
@@ -131,22 +144,28 @@ public sealed interface CharacterRangeInfo
* if&lt;cond&gt;, ifnonull, ifnull or goto.
* </ul>
* <p>
* All bits of the flags item not assigned above are reserved for future use. They should be set to zero in generated class files and should be ignored by Java virtual machine implementations.
* All bits of the flags item not assigned above are reserved for future use.
* They should be set to zero in generated class files and should be ignored
* by Java virtual machine implementations.
*
* @return the flags
* @see CharacterRange#flags()
*/
int flags();
/**
* {@return a character range description}
* @param startPc the start of the bytecode range, inclusive
* @param endPc the end of the bytecode range, exclusive
* @param characterRangeStart the start of the character range, inclusive,
* encoded as {@code line_number << 10 + column_number}
* @param characterRangeEnd the end of the character range, exclusive,
* encoded as {@code line_number << 10 + column_number}
* @param flags the range flags
* {@return a character range entry}
*
* @apiNote
* The created entry cannot be written to a {@link CodeBuilder}. Use
* {@link CodeBuilder#characterRange CodeBuilder::characterRange} instead.
*
* @param startPc the start of indices in the code array, inclusive
* @param endPc the end of indices in the code array, exclusive
* @param characterRangeStart the encoded start of character positions in
* the source file, inclusive
* @param characterRangeEnd the encoded end of character positions in the
* source file, exclusive
* @param flags the flags of this entry
*/
static CharacterRangeInfo of(int startPc,
int endPc,

View File

@@ -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,37 +26,48 @@
package java.lang.classfile.attribute;
import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper;
import java.lang.classfile.AttributeMapper.AttributeStability;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeModel;
import java.lang.classfile.instruction.CharacterRange;
import java.util.List;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* The CharacterRangeTable attribute is an optional variable-length attribute in
* the attributes table of a {@code Code} attribute. It may be used by debuggers
* to determine which part of the Java virtual machine code array corresponds to
* a given position in the source file or to determine what section of source
* code corresponds to a given index into the code array. The
* CharacterRangeTable attribute consists of an array of character range entries.
* Each character range entry within the table associates a range of indices in
* the code array with a range of character indices in the source file. If the
* source file is viewed as an array of characters, a character index is the
* corresponding index into this array. Note that character indices are not the
* same as byte indices as multi-byte characters may be present in the source
* file. Each character range entry includes a flag which indicates what kind of
* range is described: statement, assignment, method call, etc. Both code index
* ranges and character ranges may nest within other ranges, but they may not
* partially overlap. Thus, a given code index may correspond to several
* character range entries and in turn several character ranges, but there will
* be a smallest character range, and for each kind of range in which it is
* enclosed there will be a smallest character range. Similarly, a given
* character index may correspond to several character range entries and in turn
* several code index ranges, but there will be a smallest code index range, and
* for each kind of range in which it is enclosed there will be a smallest code
* index range. The character range entries may appear in any order.
* Models the {@link Attributes#characterRangeTable() CharacterRangeTable}
* attribute, which is a bidirectional mapping from ranges of positions in the
* source file to ranges of indices into the {@code code} array. Its entries
* are delivered as {@link CharacterRange}s when traversing the elements of a
* {@link CodeModel}, toggled by {@link ClassFile.DebugElementsOption}.
* <p>
* The attribute permits multiple instances in a given location.
* The {@code CharacterRangeTable} attribute consists of an array of {@linkplain
* CharacterRangeInfo character range entries}. The character range entries
* form a forest data structure: any two range entries are either disjoint, or
* if they overlap, then one entry must be enclosed within the other, both in
* {@code code} array indices and source file character positions. The
* character range entries may appear in any order.
* <p>
* This attribute only appears on {@code Code} attributes, permits multiple
* appearances but should only {@linkplain AttributeMapper#allowMultiple()
* appear once} in a {@code Code} attribute. It has a data dependency on
* {@linkplain AttributeStability#LABELS labels}.
* <p>
* This attribute cannot be sent to a {@link CodeBuilder}; its entries can be
* constructed with {@link CharacterRange}, resulting in at most one
* attribute instance in the built {@code Code} attribute.
* <p>
* This attribute is not predefined in the Java SE Platform. This is a
* JDK-specific nonstandard attribute produced by the reference implementation
* of the system Java compiler, defined by the {@code jdk.compiler} module.
*
* @see Attributes#characterRangeTable()
* @see CompilationIDAttribute
* @see SourceIDAttribute
* @since 24
*/
public sealed interface CharacterRangeTableAttribute
@@ -71,6 +82,11 @@ public sealed interface CharacterRangeTableAttribute
/**
* {@return a {@code CharacterRangeTable} attribute}
*
* @apiNote
* The created attribute cannot be written to a {@link CodeBuilder}. Use
* {@link CodeBuilder#characterRange CodeBuilder::characterRange} instead.
*
* @param ranges the descriptions of the character ranges
*/
static CharacterRangeTableAttribute of(List<CharacterRangeInfo> ranges) {

Some files were not shown because too many files have changed in this diff Show More