Compare commits

..

36 Commits

Author SHA1 Message Date
Vitaly Provodin
c1bc600440 fixup! update exclude list on results of 25.186 test runs 2025-10-30 02:27:01 +04:00
Vitaly Provodin
4ac6ef25e6 update exclude list on results of 25.186 test runs 2025-10-26 12:32:08 +04:00
Rob McKenna
a336a88057 8367031: [backout] Change java.time month/day field types to 'byte'
Backport-of: 00be643fa3eff6fd66d39f5f5ea70ff347296318
2025-10-26 03:05:42 +04:00
Nibedita Jena
6c753b5d49 8368308: ISO 4217 Amendment 180 Update
Backport-of: 3f9c665586705c833674ae998f49cabbc7e15615
2025-10-26 03:05:41 +04:00
Nibedita Jena
099394e43a 8366223: ZGC: ZPageAllocator::cleanup_failed_commit_multi_partition is broken
Backport-of: 009612805f79e37d9ce4e3f5c90627b635b095cf
2025-10-26 03:05:41 +04:00
Matias Saavedra Silva
71241ecc59 8352637: Enhance bytecode verification
Reviewed-by: dlong
Backport-of: d9bf0c2ca2d52d783a8122504cac9566d42b22df
2025-10-26 03:05:41 +04:00
Nibedita Jena
377b0902b1 8360647: [XWayland] [OL10] NumPad keys are not triggered
Backport-of: 4d5fb6eb8bb66556f06dada72df531d537cf32c2
2025-10-26 03:05:41 +04:00
Ravi Reddy
04fdd306ab 8356294: Enhance Path Factories
Backport-of: 5835cefe4946524af3be4933b20cd1b0005b0ad0
2025-10-26 03:05:40 +04:00
Nibedita Jena
06b190878a 8361212: Remove AffirmTrust root CAs
Backport-of: e58859e8acc19bfd8aaa80e98534651e83850a97
2025-10-26 03:05:40 +04:00
Nibedita Jena
b8cfdc28dc 8360937: Enhance certificate handling
Reviewed-by: mullan
Backport-of: f2fba5a55176ca82985ca42996cef36be7b7500a
2025-10-26 03:05:40 +04:00
Taizo Kurashige
1e7ae9c8d5 8358819: The first year is not displayed correctly in Japanese Calendar
Backport-of: 99829950f6
2025-10-26 03:05:39 +04:00
Dingli Zhang
0c7f8b1b00 8361829: [TESTBUG] RISC-V: compiler/vectorization/runner/BasicIntOpTest.java fails with RVV but not Zvbb
Backport-of: 2e7e272d7b
2025-10-26 03:05:39 +04:00
Dingli Zhang
3f53deeaf2 8361532: RISC-V: Several vector tests fail after JDK-8354383
Backport-of: e0245682c8
2025-10-26 03:05:39 +04:00
Matthias Baesken
a2f4b57bb2 8357826: Avoid running some jtreg tests when asan is configured
Backport-of: d7aa349820
2025-10-26 03:05:38 +04:00
Kieran Farrell
a471e942e4 8359454: Enhance String handling
Backport-of: 2f2665738a67aeed224b54870608a346eb627d2a
2025-10-26 03:05:38 +04:00
Ian Myers
d5ceea456c 8358577: Test serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java failed: unexpexcted monitor object
Backport-of: 8f487d26c0
2025-10-26 03:05:38 +04:00
Matthias Baesken
e6cb0a1b56 8360533: ContainerRuntimeVersionTestUtils fromVersionString fails with some docker versions
Backport-of: 97ec9d3e0a
2025-10-26 03:05:38 +04:00
Renjith Kannath Pariyangad
ab7a9f8f87 8358452: JNI exception pending in Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl of screencast_pipewire.c:1214 (ID: 51119)
Backport-of: 2103dc15cb
2025-10-26 03:05:37 +04:00
Fei Yang
6b43d1a768 8359270: C2: alignment check should consider base offset when emitting arraycopy runtime call
Backport-of: 6b4393917a
2025-10-26 03:05:37 +04:00
Fei Yang
dfe78a31f5 8360179: RISC-V: Only enable BigInteger intrinsics when AvoidUnalignedAccess == false
Backport-of: 34412da52b
2025-10-26 03:05:37 +04:00
Fei Yang
e48181b9aa 8359218: RISC-V: Only enable CRC32 intrinsic when AvoidUnalignedAccess == false
Backport-of: 65e63b6ab4
2025-10-26 03:05:36 +04:00
Rob McKenna
f0d54ab6e5 8359059: Bump version numbers for 25.0.1
Reviewed-by: iris
2025-10-26 03:05:36 +04:00
Vitaly Provodin
20b513f189 JBR-4154 use -V to sort versions 2025-10-26 03:05:28 +04:00
Vitaly Provodin
58f04296e7 fixup! update exclude list on results of 25.176.2 test runs 2025-10-26 03:05:10 +04:00
Maxim Kartashev
7a2d71329d JBR-9503 Wayland: IDE frame disappears after click on 'Cancel' 2025-10-24 13:39:30 +04:00
Maxim Kartashev
54276e869b JBR-9521 sources/TestNoNULL.java: Test found 14 usages of 'NULL' in source files 2025-10-23 12:13:29 +04:00
Ilia K
75dcbe8f20 JBR-9515 Allow size of per-directory buffer used to retrieve events to be configurable to avoid OVERFLOW_EVENT 2025-10-22 14:19:59 +04:00
Nikita Tsarev
37b13e2f17 JBR-9527: Fix NPE with WLDataDevice.performDeletionsOnEDT() when headless [WLToolkit] 2025-10-22 11:57:25 +02:00
Vitaly Provodin
bde37c774a update exclude list on results of 25.176.2 test runs 2025-10-22 07:30:54 +04:00
Nikita Tsarev
8dfd14f671 JBR-8353: Use a deletion queue to destroy data transfer objects [WLToolkit] 2025-10-20 21:09:46 +02:00
Nikita Gubarkov
49bed44184 JBR-9486 Vulkan: Handle VK_ERROR_OUT_OF_DATE_KHR 2025-10-16 20:32:31 +02:00
Vitaly Provodin
a270d9e6a3 clean up fixed issues from exclude lists, start 2026.1 2025-10-16 14:48:45 +04:00
Vitaly Provodin
11e3c06ba0 update exclude list on results of 25.165.38 test runs 2025-10-16 06:50:07 +04:00
Nikita Gubarkov
95c6f7c37f JBR-9481 Vulkan: OOM-safe BLIT 2025-10-15 18:44:53 +02:00
Nikita Provotorov
c4f2b64d19 JBR-5672: Wayland: support input methods.
Providing support of the "text-input-unstable-v3" protocol, except its surrounding text API (zwp_text_input_v3::set_surrounding_text + zwp_text_input_v3::delete_surrounding_text).
A new system property "sun.awt.wl.im.enabled"[=true|false] is introduced to enable/disable all the integrations with Wayland's native input methods. Set to 'true' by default.

(cherry picked from commit 1c37490f00)
2025-10-15 03:43:41 +02:00
Nikita Provotorov
9a6415585d fixup! JBR-6376: implement detecting of OS theme on linux
Adding the D-Bus libs as a dependency: it's required for src/java.desktop/linux/native/libawt/awt/dbus_interface.h

(cherry picked from commit 3fb240f4aa)
2025-10-14 20:53:18 +02:00
119 changed files with 5349 additions and 1278 deletions

2
.github/README.md vendored
View File

@@ -161,7 +161,7 @@ Install the necessary tools, libraries, and headers with:
```
$ sudo apt-get install autoconf make build-essential libx11-dev libxext-dev libxrender-dev libxtst-dev \
libxt-dev libxrandr-dev libcups2-dev libfontconfig1-dev libasound2-dev libspeechd-dev libwayland-dev \
wayland-protocols libxkbcommon-x11-0
wayland-protocols libxkbcommon-x11-0 libdbus-1-dev
```
Get Java 23 (for instance, [Azul Zulu Builds of OpenJDK 23](https://www.azul.com/downloads/?version=java-23&os=linux&package=jdk#zulu)).

View File

@@ -1,7 +1,7 @@
[general]
project=jdk
project=jdk-updates
jbs=JDK
version=25
version=25.0.1
[checks]
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists,copyright

View File

@@ -47,8 +47,8 @@ VERSION_PATCH=$(getVersionProp "DEFAULT_VERSION_PATCH")
[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}"
[[ $VERSION_PATCH = 0 ]] || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}.${VERSION_PATCH}"
echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']"
tag_prefix="jdk-"
OPENJDK_TAG=$(git tag -l | grep "$tag_prefix$JBSDK_VERSION" | grep -v ga | sort -t "-" -k 2 -V -f | tail -n 1)
tag_prefix="jbr-"
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "${tag_prefix}${JBSDK_VERSION}" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -V -f | tail -n 1 | tr -d ",")
JDK_BUILD_NUMBER=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
re='^[0-9]+$'

View File

@@ -28,12 +28,12 @@
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_UPDATE=1
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2025-09-16
DEFAULT_VERSION_DATE=2025-10-21
DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11

View File

@@ -542,10 +542,10 @@ class Bundle {
if (pattern != null) {
// Perform date-time format pattern conversion which is
// applicable to both SimpleDateFormat and j.t.f.DateTimeFormatter.
String transPattern = translateDateFormatLetters(calendarType, pattern, this::convertDateTimePatternLetter);
String transPattern = translateDateFormatLetters(calendarType, key, pattern, this::convertDateTimePatternLetter);
dateTimePatterns.add(i, transPattern);
// Additionally, perform SDF specific date-time format pattern conversion
sdfPatterns.add(i, translateDateFormatLetters(calendarType, transPattern, this::convertSDFLetter));
sdfPatterns.add(i, translateDateFormatLetters(calendarType, key, transPattern, this::convertSDFLetter));
} else {
dateTimePatterns.add(i, null);
sdfPatterns.add(i, null);
@@ -568,7 +568,7 @@ class Bundle {
}
}
private String translateDateFormatLetters(CalendarType calendarType, String cldrFormat, ConvertDateTimeLetters converter) {
private String translateDateFormatLetters(CalendarType calendarType, String patternKey, String cldrFormat, ConvertDateTimeLetters converter) {
String pattern = cldrFormat;
int length = pattern.length();
boolean inQuote = false;
@@ -587,7 +587,7 @@ class Bundle {
if (nextc == '\'') {
i++;
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -597,7 +597,7 @@ class Bundle {
}
if (!inQuote) {
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -614,7 +614,7 @@ class Bundle {
}
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -627,7 +627,7 @@ class Bundle {
count++;
continue;
}
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = c;
count = 1;
}
@@ -637,7 +637,7 @@ class Bundle {
}
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
}
if (cldrFormat.contentEquals(jrePattern)) {
return cldrFormat;
@@ -661,7 +661,7 @@ class Bundle {
* on the support given by the SimpleDateFormat and the j.t.f.DateTimeFormatter
* for date-time formatting.
*/
private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
private void convertDateTimePatternLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) {
switch (cldrLetter) {
case 'u':
case 'U':
@@ -683,7 +683,7 @@ class Bundle {
* Perform a conversion of CLDR date-time format pattern letter which is
* specific to the SimpleDateFormat.
*/
private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
private void convertSDFLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) {
switch (cldrLetter) {
case 'G':
if (calendarType != CalendarType.GREGORIAN) {
@@ -722,6 +722,17 @@ class Bundle {
appendN('z', count, sb);
break;
case 'y':
// If the style is FULL/LONG for a Japanese Calendar, make the
// count == 4 for Gan-nen
if (calendarType == CalendarType.JAPANESE &&
(patternKey.contains("full-") ||
patternKey.contains("long-"))) {
count = 4;
}
appendN(cldrLetter, count, sb);
break;
case 'Z':
if (count == 4 || count == 5) {
sb.append("XXX");
@@ -767,6 +778,7 @@ class Bundle {
.collect(Collectors.toMap(
e -> calendarPrefix + e.getKey(),
e -> translateDateFormatLetters(calendarType,
e.getKey(),
(String)e.getValue(),
this::convertDateTimePatternLetter)
))
@@ -775,7 +787,7 @@ class Bundle {
@FunctionalInterface
private interface ConvertDateTimeLetters {
void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb);
void convert(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb);
}
/**

View File

@@ -36,6 +36,7 @@ WAYLAND_BASIC_PROTOCOL_FILES := \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/primary-selection/primary-selection-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/xdg-output/xdg-output-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/relative-pointer/relative-pointer-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/text-input/text-input-unstable-v3.xml \
$(GTK_SHELL1_PROTOCOL_PATH) \
#

View File

@@ -5344,42 +5344,6 @@ void MacroAssembler::add2_with_carry(Register final_dest_hi, Register dest_hi, R
add(final_dest_hi, dest_hi, carry);
}
/**
* Multiply 32 bit by 32 bit first loop.
*/
void MacroAssembler::multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,
Register idx, Register kdx) {
// jlong carry, x[], y[], z[];
// for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) {
// long product = y[idx] * x[xstart] + carry;
// z[kdx] = (int)product;
// carry = product >>> 32;
// }
// z[xstart] = (int)carry;
Label L_first_loop, L_first_loop_exit;
blez(idx, L_first_loop_exit);
shadd(t0, xstart, x, t0, LogBytesPerInt);
lwu(x_xstart, Address(t0, 0));
bind(L_first_loop);
subiw(idx, idx, 1);
shadd(t0, idx, y, t0, LogBytesPerInt);
lwu(y_idx, Address(t0, 0));
mul(product, x_xstart, y_idx);
add(product, product, carry);
srli(carry, product, 32);
subiw(kdx, kdx, 1);
shadd(t0, kdx, z, t0, LogBytesPerInt);
sw(product, Address(t0, 0));
bgtz(idx, L_first_loop);
bind(L_first_loop_exit);
}
/**
* Multiply 64 bit by 64 bit first loop.
*/
@@ -5596,77 +5560,16 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi
const Register carry = tmp5;
const Register product = xlen;
const Register x_xstart = tmp0;
const Register jdx = tmp1;
mv(idx, ylen); // idx = ylen;
addw(kdx, xlen, ylen); // kdx = xlen+ylen;
mv(carry, zr); // carry = 0;
Label L_multiply_64_x_64_loop, L_done;
Label L_done;
subiw(xstart, xlen, 1);
bltz(xstart, L_done);
const Register jdx = tmp1;
if (AvoidUnalignedAccesses) {
int base_offset = arrayOopDesc::base_offset_in_bytes(T_INT);
assert((base_offset % (UseCompactObjectHeaders ? 4 :
(UseCompressedClassPointers ? 8 : 4))) == 0, "Must be");
if ((base_offset % 8) == 0) {
// multiply_64_x_64_loop emits 8-byte load/store to access two elements
// at a time from int arrays x and y. When base_offset is 8 bytes, these
// accesses are naturally aligned if both xlen and ylen are even numbers.
orr(t0, xlen, ylen);
test_bit(t0, t0, 0);
beqz(t0, L_multiply_64_x_64_loop);
}
Label L_second_loop_unaligned, L_third_loop, L_third_loop_exit;
multiply_32_x_32_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
shadd(t0, xstart, z, t0, LogBytesPerInt);
sw(carry, Address(t0, 0));
bind(L_second_loop_unaligned);
mv(carry, zr);
mv(jdx, ylen);
subiw(xstart, xstart, 1);
bltz(xstart, L_done);
subi(sp, sp, 2 * wordSize);
sd(z, Address(sp, 0));
sd(zr, Address(sp, wordSize));
shadd(t0, xstart, z, t0, LogBytesPerInt);
addi(z, t0, 4);
shadd(t0, xstart, x, t0, LogBytesPerInt);
lwu(product, Address(t0, 0));
blez(jdx, L_third_loop_exit);
bind(L_third_loop);
subiw(jdx, jdx, 1);
shadd(t0, jdx, y, t0, LogBytesPerInt);
lwu(t0, Address(t0, 0));
mul(t1, t0, product);
add(t0, t1, carry);
shadd(tmp6, jdx, z, t1, LogBytesPerInt);
lwu(t1, Address(tmp6, 0));
add(t0, t0, t1);
sw(t0, Address(tmp6, 0));
srli(carry, t0, 32);
bgtz(jdx, L_third_loop);
bind(L_third_loop_exit);
ld(z, Address(sp, 0));
addi(sp, sp, 2 * wordSize);
shadd(t0, xstart, z, t0, LogBytesPerInt);
sw(carry, Address(t0, 0));
j(L_second_loop_unaligned);
}
bind(L_multiply_64_x_64_loop);
multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
Label L_second_loop_aligned;

View File

@@ -1384,10 +1384,6 @@ public:
void adc(Register dst, Register src1, Register src2, Register carry);
void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo,
Register src1, Register src2, Register carry);
void multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,
Register idx, Register kdx);
void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,

View File

@@ -8431,6 +8431,17 @@ instruct castVV(vReg dst)
ins_pipe(pipe_class_empty);
%}
instruct castVVMask(vRegMask dst)
%{
match(Set dst (CastVV dst));
size(0);
format %{ "# castVV of $dst" %}
ins_encode(/* empty encoding */);
ins_cost(0);
ins_pipe(pipe_class_empty);
%}
// ============================================================================
// Convert Instructions

View File

@@ -203,15 +203,15 @@ void VM_Version::common_initialize() {
}
}
// Misc Intrinsics could depend on RVV
// Misc Intrinsics that could depend on RVV.
if (UseZba || UseRVV) {
if (!AvoidUnalignedAccesses && (UseZba || UseRVV)) {
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, true);
}
} else {
if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
warning("CRC32 intrinsic requires Zba or RVV instructions (not available on this CPU)");
warning("CRC32 intrinsic are not available on this CPU.");
}
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
@@ -325,20 +325,40 @@ void VM_Version::c2_initialize() {
FLAG_SET_DEFAULT(UseMulAddIntrinsic, true);
}
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true);
}
} else if (UseMultiplyToLenIntrinsic) {
warning("Intrinsics for BigInteger.multiplyToLen() not available on this CPU.");
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true);
}
} else if (UseSquareToLenIntrinsic) {
warning("Intrinsics for BigInteger.squareToLen() not available on this CPU.");
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true);
}
} else if (UseMontgomeryMultiplyIntrinsic) {
warning("Intrinsics for BigInteger.montgomeryMultiply() not available on this CPU.");
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
}
} else if (UseMontgomerySquareIntrinsic) {
warning("Intrinsics for BigInteger.montgomerySquare() not available on this CPU.");
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
}
// Adler32

View File

@@ -1507,7 +1507,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, Klass** reference_klass)
oop java_lang_Class::primitive_mirror(BasicType t) {
oop mirror = Universe::java_mirror(t);
assert(mirror != nullptr && (mirror->is_a(vmClasses::Class_klass())
|| (Universe::is_inside_redefinition() && vmClasses::Class_klass()->old_version() != NULL && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
|| (Universe::is_inside_redefinition() && vmClasses::Class_klass()->old_version() != nullptr && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
assert(is_primitive(mirror), "must be primitive");
return mirror;
}

View File

@@ -132,8 +132,16 @@ bool StackMapTable::match_stackmap(
}
void StackMapTable::check_jump_target(
StackMapFrame* frame, int32_t target, TRAPS) const {
StackMapFrame* frame, int bci, int offset, TRAPS) const {
ErrorContext ctx;
// Jump targets must be within the method and the method size is limited. See JVMS 4.11
int min_offset = -1 * max_method_code_size;
if (offset < min_offset || offset > max_method_code_size) {
frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame),
"Illegal target of jump or branch (bci %d + offset %d)", bci, offset);
return;
}
int target = bci + offset;
bool match = match_stackmap(
frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
if (!match || (target < 0 || target >= _code_length)) {

View File

@@ -67,7 +67,7 @@ class StackMapTable : public StackObj {
// Check jump instructions. Make sure there are no uninitialized
// instances on backward branch.
void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const;
void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const;
// The following methods are only used inside this class.

View File

@@ -1360,7 +1360,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* ol
ClassLoaderData* loader_data = k->class_loader_data();
assert(loader_data->class_loader() == class_loader(), "they must be the same");
bool is_redefining = (old_klass != NULL);
bool is_redefining = (old_klass != nullptr);
// Bootstrap and other parallel classloaders don't acquire a lock,
// they use placeholder token.
@@ -1487,7 +1487,7 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl
}
}
define_instance_class(k, NULL, class_loader, THREAD);
define_instance_class(k, nullptr, class_loader, THREAD);
// definer must notify any waiting threads
{
@@ -1527,7 +1527,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
// (DCEVM) - remove from klass hierarchy
void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
assert(k != NULL, "just checking");
assert(k != nullptr, "just checking");
// remove receiver from sibling list
k->remove_from_sibling_list();

View File

@@ -781,7 +781,6 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
// Merge with the next instruction
{
int target;
VerificationType type, type2;
VerificationType atype;
@@ -1606,9 +1605,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifle:
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_if_acmpeq :
case Bytecodes::_if_acmpne :
@@ -1619,19 +1617,16 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifnonnull :
current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target
(&current_frame, target, CHECK_VERIFY(this));
(&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_goto_w :
target = bcs.dest_w();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_tableswitch :
case Bytecodes::_lookupswitch :
@@ -2280,15 +2275,14 @@ void ClassVerifier::verify_switch(
}
}
}
int target = bci + default_offset;
stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this));
stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this));
for (int i = 0; i < keys; i++) {
// Because check_jump_target() may safepoint, the bytecode could have
// moved, which means 'aligned_bcp' is no good and needs to be recalculated.
aligned_bcp = align_up(bcs->bcp() + 1, jintSize);
target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
stackmap_table->check_jump_target(
current_frame, target, CHECK_VERIFY(this));
current_frame, bci, offset, CHECK_VERIFY(this));
}
NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point
}
@@ -2549,7 +2543,12 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
case Bytecodes::_goto:
case Bytecodes::_goto_w: {
int target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w());
int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4());
int min_offset = -1 * max_method_code_size;
// Check offset for overflow
if (offset < min_offset || offset > max_method_code_size) return false;
int target = bci + offset;
if (visited_branches->contains(bci)) {
if (bci_stack->is_empty()) {
if (handler_stack->is_empty()) {
@@ -2607,7 +2606,10 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
// Push the switch alternatives onto the stack.
for (int i = 0; i < keys; i++) {
int target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
int min_offset = -1 * max_method_code_size;
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
if (offset < min_offset || offset > max_method_code_size) return false;
int target = bci + offset;
if (target > code_length) return false;
bci_stack->push(target);
}

View File

@@ -2353,7 +2353,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
}
if (AllowEnhancedClassRedefinition) {
// Skip redefined methods
if (task->method()->is_old() || task->method()->method_holder()->new_version() != NULL) {
if (task->method()->is_old() || task->method()->method_holder()->new_version() != nullptr) {
ci_env.record_method_not_compilable("redefined method", true);
} else {
comp->compile_method(&ci_env, target, osr_bci, true, directive);

View File

@@ -231,11 +231,11 @@ uint G1FullGCCompactionPoint::find_contiguous_before(G1HeapRegion* hr, uint num_
}
HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) {
assert(_current_region != NULL, "Must have been initialized");
assert(_current_region != nullptr, "Must have been initialized");
// Ensure the object fit in the current region.
while (!object_will_fit(size)) {
if (!_compaction_region_iterator.has_next()) {
return NULL;
return nullptr;
}
switch_region();
}
@@ -243,7 +243,7 @@ HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) {
}
void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_forward) {
assert(_current_region != NULL, "Must have been initialized");
assert(_current_region != nullptr, "Must have been initialized");
// Ensure the object fit in the current region.
while (!object_will_fit(size)) {

View File

@@ -1936,7 +1936,7 @@ void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAlloca
}
const size_t committed = allocation->committed_capacity();
const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested());
const ZVirtualMemory non_harvested_vmem = partial_vmem.last_part(allocation->harvested());
const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed);
const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed);

View File

@@ -214,9 +214,20 @@ void ZPhysicalMemoryManager::free(const ZVirtualMemory& vmem, uint32_t numa_id)
});
}
static size_t inject_commit_limit(const ZVirtualMemory& vmem) {
// To facilitate easier interoperability with multi partition allocations we
// divide by ZNUMA::count(). Users of ZFailLargerCommits need to be aware of
// this when writing tests. In the future we could probe the VirtualMemoryManager
// and condition this division on whether the vmem is in the multi partition
// address space.
return align_up(MIN2(ZFailLargerCommits / ZNUMA::count(), vmem.size()), ZGranuleSize);
}
size_t ZPhysicalMemoryManager::commit(const ZVirtualMemory& vmem, uint32_t numa_id) {
zbacking_index* const pmem = _physical_mappings.addr(vmem.start());
const size_t size = vmem.size();
const size_t size = ZFailLargerCommits > 0
? inject_commit_limit(vmem)
: vmem.size();
size_t total_committed = 0;

View File

@@ -118,6 +118,11 @@
develop(bool, ZVerifyOops, false, \
"Verify accessed oops") \
\
develop(size_t, ZFailLargerCommits, 0, \
"Commits larger than ZFailLargerCommits will be truncated, " \
"used to stress page allocation commit failure paths " \
"(0: Disabled)") \
\
develop(uint, ZFakeNUMA, 1, \
"ZFakeNUMA is used to test the internal NUMA memory support " \
"without the need for UseNUMA") \

View File

@@ -100,8 +100,23 @@ class BaseBytecodeStream: StackObj {
void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
// Bytecode-specific attributes
int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }
int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }
int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); }
int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); }
// These methods are not safe to use before or during verification as they may
// have large offsets and cause overflows
int dest() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s2(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
int dest_w() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s4(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
// One-byte indices.
u1 get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }

View File

@@ -521,7 +521,7 @@ void Klass::initialize_supers(Klass* k, Array<InstanceKlass*>* transitive_interf
_primary_supers[0] = this;
assert(super_depth() == 0, "Object must already be initialized properly");
} else if (k != super() || k == vmClasses::Object_klass() || (k->is_redefining() && k == vmClasses::Object_klass()->newest_version())) {
assert(super() == NULL || super() == vmClasses::Object_klass() || (k->is_redefining() && super() == vmClasses::Object_klass()->newest_version()),
assert(super() == nullptr || super() == vmClasses::Object_klass() || (k->is_redefining() && super() == vmClasses::Object_klass()->newest_version()),
"initialize this only once to a non-trivial value");
set_super(k);
Klass* sup = k;
@@ -1388,18 +1388,18 @@ void Klass::on_secondary_supers_verification_failure(Klass* super, Klass* sub, b
}
void Klass::update_supers_dcevm() {
if (_super != NULL) {
if (_super != nullptr) {
_super = _super->newest_version();
}
int sup_depth = super_depth();
for (int idx = 0; idx < sup_depth; idx++) {
Klass* primary = _primary_supers[idx];
if (primary == NULL) {
if (primary == nullptr) {
break;
}
_primary_supers[idx] = primary->newest_version();
}
if (secondary_super_cache() != NULL) {
if (secondary_super_cache() != nullptr) {
set_secondary_super_cache(secondary_super_cache()->newest_version());
}

View File

@@ -1575,9 +1575,14 @@ bool LibraryCallKit::inline_string_toBytesU() {
Node* src_start = array_element_address(value, offset, T_CHAR);
Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE));
// Check if src array address is aligned to HeapWordSize (dst is always aligned)
const TypeInt* toffset = gvn().type(offset)->is_int();
bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
// Check if dst array address is aligned to HeapWordSize
bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0);
// If true, then check if src array address is aligned to HeapWordSize
if (aligned) {
const TypeInt* toffset = gvn().type(offset)->is_int();
aligned = toffset->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) +
toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
}
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";
@@ -1658,8 +1663,8 @@ bool LibraryCallKit::inline_string_getCharsU() {
// Check if array addresses are aligned to HeapWordSize
const TypeInt* tsrc = gvn().type(src_begin)->is_int();
const TypeInt* tdst = gvn().type(dst_begin)->is_int();
bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";

View File

@@ -1473,9 +1473,14 @@ void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array,
Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE);
Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE);
// Check if destination address is aligned to HeapWordSize
const TypeInt* tdst = __ gvn().type(start)->is_int();
bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0);
// Check if src array address is aligned to HeapWordSize
bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0);
// If true, then check if dst array address is aligned to HeapWordSize
if (aligned) {
const TypeInt* tdst = __ gvn().type(start)->is_int();
aligned = tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) +
tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0);
}
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";
address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true);

View File

@@ -218,7 +218,7 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, int offset) {
DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
if (AllowEnhancedClassRedefinition) {
while (field_klass->old_version() != NULL) {
while (field_klass->old_version() != nullptr) {
field_klass = field_klass->old_version();
}
}
@@ -242,7 +242,7 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
if (AllowEnhancedClassRedefinition) {
while (k->old_version() != NULL) {
while (k->old_version() != nullptr) {
k = k->old_version();
}
}

View File

@@ -1097,6 +1097,22 @@ bool WhiteBox::validate_cgroup(bool cgroups_v2_enabled,
}
#endif
bool WhiteBox::is_asan_enabled() {
#ifdef ADDRESS_SANITIZER
return true;
#else
return false;
#endif
}
bool WhiteBox::is_ubsan_enabled() {
#ifdef UNDEFINED_BEHAVIOR_SANITIZER
return true;
#else
return false;
#endif
}
bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) {
// Screen for unavailable/bad comp level or null method
AbstractCompiler* comp = CompileBroker::compiler(comp_level);
@@ -1908,6 +1924,14 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
return (jboolean) obj_oop->mark().has_monitor();
WB_END
WB_ENTRY(jboolean, WB_IsAsanEnabled(JNIEnv* env))
return (jboolean) WhiteBox::is_asan_enabled();
WB_END
WB_ENTRY(jboolean, WB_IsUbsanEnabled(JNIEnv* env))
return (jboolean) WhiteBox::is_ubsan_enabled();
WB_END
WB_ENTRY(jlong, WB_getInUseMonitorCount(JNIEnv* env, jobject wb))
return (jlong) WhiteBox::get_in_use_monitor_count();
WB_END
@@ -2908,6 +2932,8 @@ static JNINativeMethod methods[] = {
(void*)&WB_AddModuleExportsToAll },
{CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"isAsanEnabled", CC"()Z", (void*)&WB_IsAsanEnabled },
{CC"isUbsanEnabled", CC"()Z", (void*)&WB_IsUbsanEnabled },
{CC"getInUseMonitorCount", CC"()J", (void*)&WB_getInUseMonitorCount },
{CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity },
{CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking },

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,6 +72,9 @@ class WhiteBox : public AllStatic {
#ifdef LINUX
static bool validate_cgroup(bool cgroups_v2_enabled, const char* controllers_file, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags);
#endif
// provide info about enabling of Address Sanitizer / Undefined Behavior Sanitizer
static bool is_asan_enabled();
static bool is_ubsan_enabled();
};
#endif // SHARE_PRIMS_WHITEBOX_HPP

View File

@@ -1448,8 +1448,8 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
shift(currValue, coder, count, dstOffset, len);
count += len;
// Coder of CharSequence may be a mismatch, requiring the value array to be inflated
byte[] newValue = (s instanceof String str)
? putStringAt(currValue, coder, count, dstOffset, str, start, end)
byte[] newValue = (s instanceof String str && str.length() == len)
? putStringAt(currValue, coder, count, dstOffset, str)
: putCharsAt(currValue, coder, count, dstOffset, s, start, end);
if (currValue != newValue) {
this.coder = UTF16;
@@ -1928,10 +1928,10 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
* @param index the index to insert the string
* @param str the string
*/
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) {
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str) {
byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder());
coder = (newValue == value) ? coder : UTF16;
str.getBytes(newValue, off, index, coder, end - off);
str.getBytes(newValue, 0, index, coder, str.length());
return newValue;
}

View File

@@ -182,11 +182,11 @@ public final class LocalDate
/**
* @serial The month-of-year.
*/
private final byte month;
private final short month;
/**
* @serial The day-of-month.
*/
private final byte day;
private final short day;
//-----------------------------------------------------------------------
/**
@@ -490,8 +490,8 @@ public final class LocalDate
*/
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
this.month = (byte) month;
this.day = (byte) dayOfMonth;
this.month = (short) month;
this.day = (short) dayOfMonth;
}
//-----------------------------------------------------------------------

View File

@@ -146,11 +146,11 @@ public final class MonthDay
/**
* @serial The month-of-year, not null.
*/
private final byte month;
private final int month;
/**
* @serial The day-of-month.
*/
private final byte day;
private final int day;
//-----------------------------------------------------------------------
/**
@@ -319,8 +319,8 @@ public final class MonthDay
* @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31
*/
private MonthDay(int month, int dayOfMonth) {
this.month = (byte) month;
this.day = (byte) dayOfMonth;
this.month = month;
this.day = dayOfMonth;
}
//-----------------------------------------------------------------------

View File

@@ -153,7 +153,7 @@ public final class YearMonth
/**
* @serial The month-of-year, not null.
*/
private final byte month;
private final int month;
//-----------------------------------------------------------------------
/**
@@ -306,7 +306,7 @@ public final class YearMonth
*/
private YearMonth(int year, int month) {
this.year = year;
this.month = (byte) month;
this.month = month;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -137,11 +137,11 @@ public final class HijrahDate
/**
* The month-of-year.
*/
private final transient byte monthOfYear;
private final transient int monthOfYear;
/**
* The day-of-month.
*/
private final transient byte dayOfMonth;
private final transient int dayOfMonth;
//-------------------------------------------------------------------------
/**
@@ -273,8 +273,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = prolepticYear;
this.monthOfYear = (byte) monthOfYear;
this.dayOfMonth = (byte) dayOfMonth;
this.monthOfYear = monthOfYear;
this.dayOfMonth = dayOfMonth;
}
/**
@@ -287,8 +287,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = dateInfo[0];
this.monthOfYear = (byte) dateInfo[1];
this.dayOfMonth = (byte) dateInfo[2];
this.monthOfYear = dateInfo[1];
this.dayOfMonth = dateInfo[2];
}
//-----------------------------------------------------------------------

View File

@@ -859,6 +859,22 @@ public class DerValue {
return readStringInternal(tag_UniversalString, new UTF_32BE());
}
/**
* Checks that the BMPString does not contain any surrogate characters,
* which are outside the Basic Multilingual Plane.
*
* @throws IOException if illegal characters are detected
*/
public void validateBMPString() throws IOException {
String bmpString = getBMPString();
for (int i = 0; i < bmpString.length(); i++) {
if (Character.isSurrogate(bmpString.charAt(i))) {
throw new IOException(
"Illegal character in BMPString, index: " + i);
}
}
}
/**
* Reads the ASN.1 NULL value
*/

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
@@ -71,19 +71,7 @@ final class EntrustTLSPolicy {
// OU=(c) 1999 Entrust.net Limited,
// OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),
// O=Entrust.net
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177",
// cacerts alias: affirmtrustcommercialca
// DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
"0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7",
// cacerts alias: affirmtrustnetworkingca
// DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US
"0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B",
// cacerts alias: affirmtrustpremiumca
// DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US
"70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A",
// cacerts alias: affirmtrustpremiumeccca
// DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
"BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423"
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177"
);
// Any TLS Server certificate that is anchored by one of the Entrust

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,13 @@ package sun.security.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.text.Normalizer;
import java.util.*;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.charset.StandardCharsets.UTF_16BE;
import sun.security.util.*;
import sun.security.pkcs.PKCS9Attribute;
@@ -589,6 +592,10 @@ public class AVA implements DerEncoder {
throw new IOException("AVA, extra bytes = "
+ derval.data.available());
}
if (value.tag == DerValue.tag_BMPString) {
value.validateBMPString();
}
}
AVA(DerInputStream in) throws IOException {
@@ -713,7 +720,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, false));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -832,7 +840,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, true));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -927,6 +936,39 @@ public class AVA implements DerEncoder {
}
}
/*
* Returns the charset that should be used to decode each DN string type.
*
* This method ensures that multi-byte (UTF8String and BMPString) types
* are decoded using the correct charset and the String forms represent
* the correct characters. For 8-bit ASCII-based types (PrintableString
* and IA5String), we return ISO_8859_1 rather than ASCII, so that the
* complete range of characters can be represented, as many certificates
* do not comply with the Internationalized Domain Name ACE format.
*
* NOTE: this method only supports DirectoryStrings of the types returned
* by isDerString().
*/
private static Charset getCharset(DerValue value, boolean canonical) {
if (canonical) {
return switch (value.tag) {
case DerValue.tag_PrintableString -> ISO_8859_1;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
return switch (value.tag) {
case DerValue.tag_PrintableString,
DerValue.tag_T61String,
DerValue.tag_IA5String,
DerValue.tag_GeneralString -> ISO_8859_1;
case DerValue.tag_BMPString -> UTF_16BE;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
boolean hasRFC2253Keyword() {
return AVAKeyword.hasKeyword(oid, RFC2253);
}

View File

@@ -1,27 +0,0 @@
Owner: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
Serial number: 7777062726a9b17c
Valid from: Fri Jan 29 14:06:06 GMT 2010 until: Tue Dec 31 14:06:06 GMT 2030
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
Owner: CN=AffirmTrust Networking, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Networking, O=AffirmTrust, C=US
Serial number: 7c4f04391cd4992d
Valid from: Fri Jan 29 14:08:24 GMT 2010 until: Tue Dec 31 14:08:24 GMT 2030
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
-----END CERTIFICATE-----

View File

@@ -1,38 +0,0 @@
Owner: CN=AffirmTrust Premium, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Premium, O=AffirmTrust, C=US
Serial number: 6d8c1446b1a60aee
Valid from: Fri Jan 29 14:10:36 GMT 2010 until: Mon Dec 31 14:10:36 GMT 2040
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
KeC2uAloGRwYQw==
-----END CERTIFICATE-----

View File

@@ -1,20 +0,0 @@
Owner: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
Serial number: 7497258ac73f7a54
Valid from: Fri Jan 29 14:20:24 GMT 2010 until: Mon Dec 31 14:20:24 GMT 2040
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
-----END CERTIFICATE-----

View File

@@ -32,7 +32,7 @@ formatVersion=3
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
dataVersion=179
dataVersion=180
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -147,7 +147,7 @@ IO=USD
# BRUNEI DARUSSALAM
BN=BND
# BULGARIA
BG=BGN
BG=BGN;2025-12-31-22-00-00;EUR
# BURKINA FASO
BF=XOF
# BURUNDI
@@ -193,7 +193,7 @@ HR=EUR
# CUBA
CU=CUP
# Curaçao
CW=ANG;2025-04-01-04-00-00;XCG
CW=XCG
# CYPRUS
CY=EUR
# CZECHIA
@@ -510,7 +510,7 @@ SR=SRD
# SVALBARD AND JAN MAYEN
SJ=NOK
# Sint Maarten (Dutch part)
SX=ANG;2025-04-01-04-00-00;XCG
SX=XCG
# ESWATINI
SZ=SZL
# SWEDEN

View File

@@ -395,7 +395,8 @@ static jboolean is_superclass(context_type *, fullinfo_type);
static void initialize_exception_table(context_type *);
static int instruction_length(unsigned char *iptr, unsigned char *end);
static jboolean isLegalTarget(context_type *, int offset);
static jboolean isLegalOffset(context_type *, int bci, int offset);
static jboolean isLegalTarget(context_type *, int target);
static void verify_constant_pool_type(context_type *, int, unsigned);
static void initialize_dataflow(context_type *);
@@ -1154,9 +1155,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
case JVM_OPC_goto: {
/* Set the ->operand to be the instruction number of the target. */
int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@@ -1170,9 +1171,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
int jump = (((signed char)(code[offset+1])) << 24) +
(code[offset+2] << 16) + (code[offset+3] << 8) +
(code[offset + 4]);
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@@ -1211,13 +1212,16 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
}
}
saved_operand = NEW(int, keys + 2);
if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0])))
int jump = _ck_ntohl(lpc[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal default target in switch");
saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])];
int target = offset + jump;
saved_operand[keys + 1] = code_data[target];
for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) {
int target = offset + _ck_ntohl(lptr[0]);
if (!isLegalTarget(context, target))
jump = _ck_ntohl(lptr[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal branch in tableswitch");
target = offset + jump;
saved_operand[k + 1] = code_data[target];
}
saved_operand[0] = keys + 1; /* number of successors */
@@ -1746,11 +1750,24 @@ static int instruction_length(unsigned char *iptr, unsigned char *end)
/* Given the target of a branch, make sure that it's a legal target. */
static jboolean
isLegalTarget(context_type *context, int offset)
isLegalTarget(context_type *context, int target)
{
int code_length = context->code_length;
int *code_data = context->code_data;
return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
return (target >= 0 && target < code_length && code_data[target] >= 0);
}
/* Given a bci and offset, make sure the offset is valid and the target is legal */
static jboolean
isLegalOffset(context_type *context, int bci, int offset)
{
int code_length = context->code_length;
int *code_data = context->code_data;
int max_offset = 65535; // JVMS 4.11
int min_offset = -65535;
if (offset < min_offset || offset > max_offset) return JNI_FALSE;
int target = bci + offset;
return (target >= 0 && target < code_length && code_data[target] >= 0);
}

View File

@@ -36,6 +36,7 @@ import java.util.Map;
import java.util.Set;
import jdk.internal.misc.Unsafe;
import jdk.internal.util.ArraysSupport;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;
@@ -284,9 +285,26 @@ class WindowsWatchService
private static final short OFFSETOF_FILENAMELENGTH = 8;
private static final short OFFSETOF_FILENAME = 12;
// size of per-directory buffer for events (FIXME - make this configurable)
// Need to be less than 4*16384 = 65536. DWORD align.
private static final int CHANGES_BUFFER_SIZE = 16 * 1024;
// size of per-directory buffer for events
// Need to be less than 4*16384 = 65536 when monitoring a directory over the network. DWORD align.
private static final int DEFAULT_CHANGES_BUFFER_SIZE = 16 * 1024;
static final int CHANGES_BUFFER_SIZE;
static {
String rawValue = System.getProperty(
"jdk.nio.file.WatchService.bufferSizeToRetrieveEventsPerDirectory",
String.valueOf(DEFAULT_CHANGES_BUFFER_SIZE));
int intValue;
try {
// Clamp to size of per-directory buffer used to retrieve events.
intValue = Math.clamp(
Long.decode(rawValue),
1,
ArraysSupport.SOFT_MAX_ARRAY_LENGTH);
} catch (NumberFormatException e) {
intValue = DEFAULT_CHANGES_BUFFER_SIZE;
}
CHANGES_BUFFER_SIZE = intValue;
}
private final WindowsFileSystem fs;
private final WindowsWatchService watcher;

View File

@@ -4377,11 +4377,6 @@ public class Window extends Container implements Accessible {
}
}
@Override
public void addWindowListener(Window w, WindowListener listener) {
w.addWindowListener(listener);
}
private static void dumpCounter(final String counterName, final double valPerSecond) {
if (USE_COUNTERS) {
doLog(String.format("%s per second: %.2f", counterName, valPerSecond),

View File

@@ -37,7 +37,6 @@ import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferStrategy;
import java.awt.peer.ComponentPeer;
@@ -338,8 +337,6 @@ public final class AWTAccessor {
double getCounterPerSecond(Window w, String counterName);
void dumpStats(Window w, boolean reset, StringBuilder sb);
void addWindowListener(Window w, WindowListener listener);
}
/**

View File

@@ -63,7 +63,7 @@
#define TRACE_USE_API 0
#define TRACE_REUSE 0
#define INIT_TEST 1
#define INIT_TEST 0
#define INIT_TEST_STEP 1
#define INIT_TEST_MAX 1024

View File

@@ -154,7 +154,7 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
}
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) {
src->GetRasInfo(env, src, &srcInfo);
if (srcInfo.rasBase) {
while (srcInfo.rasBase) {
if (srcInfo.bounds.x1 != sx1) dx1 += (srcInfo.bounds.x1 - sx1) * (dx2 - dx1) / (sx2 - sx1);
if (srcInfo.bounds.y1 != sy1) dy1 += (srcInfo.bounds.y1 - sy1) * (dy2 - dy1) / (sy2 - sy1);
if (srcInfo.bounds.x2 != sx2) dx2 += (srcInfo.bounds.x2 - sx2) * (dx2 - dx1) / (sx2 - sx1);
@@ -165,13 +165,17 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
// Need to validate render pass early, as image may not yet be configured.
AlphaType alphaType = getSrcAlphaType(srctype);
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) break;
VKDevice* device = context->surface->device;
BlitSrcType type = decodeSrcType(device, srctype);
VKTexturePoolHandle* imageHandle =
VKTexturePool_GetTexture(VKRenderer_GetTexturePool(device->renderer), sw, sh, type.format);
VKImage* image = VKTexturePoolHandle_GetTexture(imageHandle);
if (!image) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKBlitLoops_Blit: could not get texture from the pool");
break;
}
VkDeviceSize dataSize = sh * sw * srcInfo.pixelStride;
VKBuffer buffer;
@@ -232,7 +236,9 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeTexture, imageHandle);
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeBuffer, buffer.handle);
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeMemory, page);
} else {
break;
}
if (!srcInfo.rasBase) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKBlitLoops_Blit: could not get raster info");
}
SurfaceData_InvokeRelease(env, src, &srcInfo);

View File

@@ -976,9 +976,12 @@ void VKRenderer_FlushSurface(VKSDOps* surface) {
uint32_t imageIndex;
VkResult acquireImageResult = device->vkAcquireNextImageKHR(device->handle, win->swapchain, UINT64_MAX,
acquireSemaphore, VK_NULL_HANDLE, &imageIndex);
if (acquireImageResult != VK_SUCCESS) {
// TODO possible suboptimal conditions
VK_IF_ERROR(acquireImageResult) {}
if (acquireImageResult != VK_SUCCESS && acquireImageResult != VK_SUBOPTIMAL_KHR) {
VK_IF_ERROR(acquireImageResult) {
// Failed, try again later.
surface->renderPass->pendingFlush = VK_TRUE;
return;
}
}
// Insert barriers to prepare both main (src) and swapchain (dst) images for blit.

View File

@@ -268,7 +268,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
return false;
}
private static Window getToplevelFor(Component component) {
public static Window getToplevelFor(Component component) {
Container container = component instanceof Container c ? c : component.getParent();
for (Container p = container; p != null; p = p.getParent()) {
if (p instanceof Window window && !isWlPopup(window)) {
@@ -285,7 +285,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
: c.getParent();
}
static Point getRelativeLocation(Component c, Window toplevel) {
public static Point getRelativeLocation(Component c, Window toplevel) {
Objects.requireNonNull(c);
if (toplevel == null) {
@@ -1590,7 +1590,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
* Converts a value in the Java coordinate system into the Wayland
* surface-local coordinate system.
*/
int javaUnitsToSurfaceUnits(int value) {
public final int javaUnitsToSurfaceUnits(int value) {
if (!WLGraphicsEnvironment.isDebugScaleEnabled()) {
return value;
} else {
@@ -1600,7 +1600,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
}
}
int javaUnitsToSurfaceSize(int value) {
public final int javaUnitsToSurfaceSize(int value) {
if (!WLGraphicsEnvironment.isDebugScaleEnabled()) {
return value;
} else {

View File

@@ -89,6 +89,7 @@ public class WLDataDevice {
private static native void setSelectionImpl(int protocol, long nativePtr, long dataOfferNativePtr, long serial);
private static native void startDragImpl(long nativePtr, long dataOfferNativePtr,
long originSurfaceNativePtr, long serial);
private static native void performDeletionsOnEDTImpl(long nativePtr);
public boolean isProtocolSupported(int protocol) {
return isProtocolSupportedImpl(nativePtr, protocol);
@@ -246,6 +247,10 @@ public class WLDataDevice {
return result;
}
public void performDeletionsOnEDT() {
performDeletionsOnEDTImpl(nativePtr);
}
// Event handlers, called from native on the EDT
private void handleDnDEnter(WLDataOffer offer, long serial, long surfacePtr, double x, double y) {
WLDropTargetContextPeer.getInstance().handleEnter(offer, serial, surfacePtr, x, y);

View File

@@ -61,7 +61,7 @@ public class WLDataOffer {
}
// after calling destroy(), this object enters an invalid state and needs to be deleted
public void destroy() {
public synchronized void destroy() {
if (nativePtr != 0) {
destroyImpl(nativePtr);
nativePtr = 0;

View File

@@ -26,7 +26,6 @@
package sun.awt.wl;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.peer.FramePeer;
import sun.awt.AWTAccessor;
@@ -43,12 +42,6 @@ public class WLFramePeer extends WLDecoratedPeer implements FramePeer {
super(target, target.isUndecorated(),
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED),
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH));
AWTAccessor.getWindowAccessor().addWindowListener(target, new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
getFrame().removeNotify();
}
});
}
@Override

View File

@@ -35,6 +35,7 @@ import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.UNIXToolkit;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.wl.im.WLInputMethodMetaDescriptor;
import sun.java2d.vulkan.VKEnv;
import sun.java2d.vulkan.VKRenderQueue;
import sun.util.logging.PlatformLogger;
@@ -82,6 +83,7 @@ import java.awt.peer.TrayIconPeer;
import java.awt.peer.WindowPeer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -172,11 +174,31 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
toolkitSystemThread.start();
dataDevice = new WLDataDevice(0); // TODO: for multiseat support pass wl_seat pointer here
registerShutdownHook();
} else {
dataDevice = null;
}
}
private void registerShutdownHook() {
Runnable r = () -> {
ArrayList<WLWindowPeer> livePeers;
synchronized (wlSurfaceToPeerMap) {
livePeers = new ArrayList<>(wlSurfaceToPeerMap.values());
}
livePeers.forEach(p -> {
Component target = p.getTarget();
if (target.isDisplayable()) {
target.removeNotify();
}
});
};
Thread shutdownThread = InnocuousThread.newSystemThread("WLToolkit-Shutdown-Thread", r);
shutdownThread.setDaemon(true);
Runtime.getRuntime().addShutdownHook(shutdownThread);
}
public static synchronized boolean getSunAwtDisableGtkFileDialogs() {
if (sunAwtDisableGtkFileDialogs == null) {
sunAwtDisableGtkFileDialogs = Boolean.getBoolean("sun.awt.disableGtkFileDialogs");
@@ -254,6 +276,9 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
WLToolkit.awtLock();
try {
dispatchEventsOnEDT();
if (dataDevice != null) {
dataDevice.performDeletionsOnEDT();
}
} finally {
eventsQueued.release();
WLToolkit.awtUnlock();
@@ -777,13 +802,27 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
return 16777216; // 24 bits per pixel, 8 bits per channel
}
/**
* {@link java.awt.event.InputMethodEvent#getText()} can contain attributes which provide AWT/Swing with additional useful information
* (e.g. a language of the text).
*
* One kind of the possible attributes is {@link InputMethodHighlight}. It informs AWT/Swing that some parts of
* the text are in different states of the text composing process, hence they should look differently from the others.
* However, it doesn't tell how exactly they should look; this choice is left to Toolkit's implementations,
* or more precisely implementations of this method.
*
* @param highlight a state of a part of InputMethodEvent's text
*
* @return a collection of {@link TextAttribute}s (with their corresponding values as documented) informing how exactly
* such text should look or {@code null} if a mapping can't be provided.
*
* @see Toolkit#mapInputMethodHighlight(InputMethodHighlight)
*/
@Override
public Map<TextAttribute, ?> mapInputMethodHighlight( InputMethodHighlight highlight) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Not implemented: WLToolkit.mapInputMethodHighlight()");
}
return null;
public Map<TextAttribute, ?> mapInputMethodHighlight(InputMethodHighlight highlight) {
return WLInputMethodMetaDescriptor.mapInputMethodHighlight(highlight);
}
@Override
public boolean getLockingKeyState(int key) {
return switch (key) {
@@ -843,10 +882,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
*/
@Override
public InputMethodDescriptor getInputMethodAdapterDescriptor() {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Not implemented: WLToolkit.getInputMethodAdapterDescriptor()");
}
return null;
return WLInputMethodMetaDescriptor.getInstanceIfAvailableOnPlatform();
}
/**
@@ -855,9 +891,6 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
*/
@Override
public boolean enableInputMethodsForTextComponent() {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Not implemented: WLToolkit.enableInputMethodsForTextComponent()");
}
return true;
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im;
import sun.awt.wl.im.text_input_unstable_v3.WLInputMethodDescriptorZwpTextInputV3;
import sun.util.logging.PlatformLogger;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.font.TextAttribute;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethod;
import java.awt.im.spi.InputMethodDescriptor;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
/**
* Since Wayland compositors may support multiple IM protocols,
* this class is responsible for choosing one specific among them,
* and the corresponding "real" implementation of {@code InputMethodDescriptor} from a subpackage.
*/
public final class WLInputMethodMetaDescriptor implements InputMethodDescriptor {
// NB: the class loading routine has to be as fast and not demanding on resources as possible.
// Also, it has to succeed in any practically possible situation.
// E.g. if the Wayland compositor doesn't support any known IM protocol,
// it mustn't prevent this class from being loaded successfully.
// Ideally, nothing additional should happen at the loading time.
//
// This class is directly used by WLToolkit to find and instantiate an InputMethod implementation.
// See java.text.MessageFormat for the formatting syntax
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.im.WLInputMethodMetaDescriptor");
/** @see sun.awt.wl.WLToolkit#mapInputMethodHighlight(InputMethodHighlight) */
public static Map<TextAttribute, ?> mapInputMethodHighlight(final InputMethodHighlight highlight) {
// NB: The implementation is supposed to produce results exactly equal to XToolkit's implementation
// for better visual consistency.
if (highlight == null)
return null;
switch (highlight.getState()) {
case InputMethodHighlight.RAW_TEXT -> {
if (highlight.isSelected())
return imHighlightMapSelectedRawText;
else
return imHighlightMapUnselectedRawText;
}
case InputMethodHighlight.CONVERTED_TEXT -> {
if (highlight.isSelected())
return imHighlightMapSelectedConvertedText;
else
return imHighlightMapUnselectedConvertedText;
}
}
return null;
}
public static WLInputMethodMetaDescriptor getInstanceIfAvailableOnPlatform() {
final WLInputMethodMetaDescriptor result;
if (!ENABLE_NATIVE_IM_SUPPORT) {
result = null;
} else {
// For now there's only 1 possible implementation of IM,
// but if/when there are more, this method will have to choose one of them.
// It'll be good if the preferable engine can be chosen via a system property.
final InputMethodDescriptor realImDescriptor = WLInputMethodDescriptorZwpTextInputV3.getInstanceIfAvailableOnPlatform();
if (realImDescriptor != null) {
result = new WLInputMethodMetaDescriptor(realImDescriptor);
} else {
result = null;
}
}
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("getInstanceIfAvailableOnPlatform(): result={0}, ENABLE_NATIVE_IM_SUPPORT={1}.", result, ENABLE_NATIVE_IM_SUPPORT);
}
return result;
}
/* java.awt.im.spi.InputMethodDescriptor methods section */
@Override
public Locale[] getAvailableLocales() throws AWTException {
final Locale[] result = realImDescriptor.getAvailableLocales();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("getAvailableLocales(): result={0}, this={1}.", Arrays.toString(result), this);
}
return result;
}
@Override
public boolean hasDynamicLocaleList() {
final boolean result = realImDescriptor.hasDynamicLocaleList();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("hasDynamicLocaleList(): result={0}, this={1}.", result, this);
}
return result;
}
@Override
public String getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage) {
return realImDescriptor.getInputMethodDisplayName(inputLocale, displayLanguage);
}
@Override
public Image getInputMethodIcon(Locale inputLocale) {
return realImDescriptor.getInputMethodIcon(inputLocale);
}
@Override
public InputMethod createInputMethod() throws Exception {
final InputMethod result = realImDescriptor.createInputMethod();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("createInputMethod(): result={0}, this={1}.", result, this);
}
return result;
}
/* java.lang.Object methods section */
@Override
public String toString() {
return String.format("WLInputMethodMetaDescriptor@%d[realImDescriptor=%s]", System.identityHashCode(this), realImDescriptor);
}
/* Implementation details section */
/**
* The values are copied from XToolkit's implementation for better visual consistency with AWT on X11.
*
* @see #mapInputMethodHighlight(InputMethodHighlight)
* @see sun.awt.X11InputMethodBase
*/
private final static Map<TextAttribute, ?> imHighlightMapUnselectedRawText = Map.of(
TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD
);
private final static Map<TextAttribute, ?> imHighlightMapUnselectedConvertedText = Map.of(
TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL
);
private final static Map<TextAttribute, ?> imHighlightMapSelectedRawText = Map.of(
TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON
);
private final static Map<TextAttribute, ?> imHighlightMapSelectedConvertedText = Map.of(
TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON
);
/**
* This flag allows disabling ALL integrations with native IMs. The idea is to allow users to disable
* unnecessary for them functionality if they face any problems because of it.
* Therefore, if it's {@code false}, the Toolkit code shouldn't use (directly or indirectly)
* any of Wayland's input methods-related APIs (e.g. the "text-input" protocol).
*/
private final static boolean ENABLE_NATIVE_IM_SUPPORT;
static {
boolean enableNativeImSupportInitializer = true;
try {
enableNativeImSupportInitializer = Boolean.parseBoolean(System.getProperty("sun.awt.wl.im.enabled", "true"));
} catch (Exception err) {
log.severe("Failed to read the value of the system property \"sun.awt.wl.im.enabled\". Assuming the default value(=true).", err);
}
ENABLE_NATIVE_IM_SUPPORT = enableNativeImSupportInitializer;
}
private final InputMethodDescriptor realImDescriptor;
private WLInputMethodMetaDescriptor(InputMethodDescriptor realImDescriptor) {
this.realImDescriptor = Objects.requireNonNull(realImDescriptor, "realImDescriptor");
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
/** Reason for the change of surrounding text or cursor position */
enum ChangeCause {
/** input method caused the change */
INPUT_METHOD(0),
/** something else than the input method caused the change */
OTHER (1);
public final int intValue;
ChangeCause(int intValue) {
this.intValue = intValue;
}
}

View File

@@ -0,0 +1,371 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import sun.util.logging.PlatformLogger;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.JTextComponent;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.TextComponent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.lang.ref.WeakReference;
import java.util.Objects;
/**
* This class is intended to track all the cases when a new {@code zwp_text_input_v3::set_cursor_rectangle} request
* may have to be issued. Here are the examples of such cases:
* <ul>
* <li>The caret position has changed ;
* <li>The component has been moved/resized ;
* <li>The component's window has been moved/resized ;
* <li>The component's text has been changed ;
* </ul>
*/
class ClientComponentCaretPositionTracker implements ComponentListener, CaretListener, TextListener
{
// See java.text.MessageFormat for the formatting syntax
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.im.text_input_unstable_v3.ClientComponentCaretPositionTracker");
public ClientComponentCaretPositionTracker(WLInputMethodZwpTextInputV3 im) {
this.im = new WeakReference<>(Objects.requireNonNull(im, "im"));
}
public void startTracking(final Component component) {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer(
String.format("startTracking(component=%s): im=%s, this=%s.", component, getOwnerIm(), this),
new Throwable("Stacktrace")
);
}
stopTrackingCurrentComponent();
if (component == null) {
return;
}
trackedComponent = new WeakReference<>(component);
lastKnownClientWindowBounds = null;
try {
// Moving and changing the size causes a possible change of caret position
component.addComponentListener(this);
if (component instanceof JTextComponent jtc) {
jtc.addCaretListener(this);
isCaretListenerInstalled = true;
} else if (component instanceof TextComponent tc) {
tc.addTextListener(this);
isTextListenerInstalled = true;
}
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("startTracking(...): updated this={0}.", this);
}
} catch (Exception err) {
stopTrackingCurrentComponent();
throw err;
}
}
public void stopTrackingCurrentComponent() {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer(String.format("stopTrackingCurrentComponent(): this=%s.", this), new Throwable("Stacktrace"));
}
final Component trackedComponentStrong = getTrackedComponentIfTracking();
if (trackedComponentStrong == null) {
return;
}
if (isTextListenerInstalled) {
isTextListenerInstalled = false;
try {
((TextComponent)trackedComponentStrong).removeTextListener(this);
} catch (Exception err) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning(String.format("stopTrackingCurrentComponent(): exception occurred while removing the text listener from %s.", trackedComponentStrong), err);
}
}
}
if (isCaretListenerInstalled) {
isCaretListenerInstalled = false;
try {
((JTextComponent)trackedComponentStrong).removeCaretListener(this);
} catch (Exception err) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning(String.format("stopTrackingCurrentComponent(): exception occurred while removing the caret listener from %s.", trackedComponentStrong), err);
}
}
}
try {
trackedComponentStrong.removeComponentListener(this);
} catch (Exception err) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning(String.format("stopTrackingCurrentComponent(): exception occurred while removing the component listener from %s.", trackedComponentStrong), err);
}
}
lastKnownClientWindowBounds = null;
updatesAreDeferred = false;
if (trackedComponent != null) {
trackedComponent.clear();
trackedComponent = null;
}
}
public Component getTrackedComponentIfTracking() {
assert(EventQueue.isDispatchThread());
final Component trackedComponentStrong;
if (trackedComponent == null) {
trackedComponentStrong = null;
} else {
trackedComponentStrong = trackedComponent.get();
}
if (trackedComponentStrong == null) {
isTextListenerInstalled = false;
isCaretListenerInstalled = false;
lastKnownClientWindowBounds = null;
updatesAreDeferred = false;
if (trackedComponent != null) {
trackedComponent.clear();
trackedComponent = null;
}
}
return trackedComponentStrong;
}
public void deferUpdates() {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer(String.format("deferUpdates(): this=%s.", this), new Throwable("Stacktrace"));
}
updatesAreDeferred = true;
}
public void resumeUpdates(final boolean discardDeferredUpdates) {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer(String.format("resumeUpdates(%b): this=%s.", discardDeferredUpdates, this), new Throwable("Stacktrace"));
}
if (getTrackedComponentIfTracking() == null) return;
updatesAreDeferred = false;
hasDeferredUpdates = hasDeferredUpdates && !discardDeferredUpdates;
if (hasDeferredUpdates) {
updateNotify();
}
}
public boolean areUpdatesDeferred() {
assert(EventQueue.isDispatchThread());
return updatesAreDeferred;
}
/* Listening callbacks */
/** This method is intended to be called from the owning IM's {@link java.awt.im.spi.InputMethod#dispatchEvent(AWTEvent)}. */
public void onIMDispatchEvent(AWTEvent event) {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("onIMDispatchEvent(event={0}): this={1}.", event, this);
}
final int eventId = event.getID();
if (eventId >= MouseEvent.MOUSE_FIRST && eventId <= MouseEvent.MOUSE_LAST) {
// MouseEvent or MouseWheelEvent
if (!isCaretListenerInstalled || eventId == MouseEvent.MOUSE_WHEEL) {
// We expect no mouse events except MouseWheelEvent can change the physical position of the caret
// without changing its logical position inside the document. The logical position is handled by caretUpdate.
// The event hasn't been handled by the component yet, so the caret position couldn't have been changed yet.
// Hence, we have to postpone the updating request.
EventQueue.invokeLater(this::updateNotify);
}
}
if (eventId >= KeyEvent.KEY_FIRST && eventId <= KeyEvent.KEY_LAST) {
if ( !isCaretListenerInstalled && (!isTextListenerInstalled || eventId != KeyEvent.KEY_TYPED) ) {
EventQueue.invokeLater(this::updateNotify);
}
}
}
/** This method is intended to be called from the owning IM's {@link java.awt.im.spi.InputMethod#notifyClientWindowChange(Rectangle)}. */
public void onIMNotifyClientWindowChange(Rectangle location) {
assert(EventQueue.isDispatchThread());
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("onIMNotifyClientWindowChange(location={0}): this={1}.", location, this);
}
if (location != null) {
// null means the window has become iconified or invisible, so no need to try to update the caret position.
lastKnownClientWindowBounds = location;
updateNotify();
}
}
// ComponentListener
@Override
public void componentHidden(ComponentEvent e) {}
@Override
public void componentMoved(ComponentEvent e) {
updateNotify();
}
@Override
public void componentResized(ComponentEvent e) {
updateNotify();
}
@Override
public void componentShown(ComponentEvent e) {
updateNotify();
}
// CaretListener
@Override
public void caretUpdate(CaretEvent e) {
updateNotify();
}
// TextListener
@Override
public void textValueChanged(TextEvent e) {
updateNotify();
}
/* java.lang.Object methods section */
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(1024);
sb.append("ClientComponentCaretPositionTracker@").append(System.identityHashCode(this));
sb.append('{');
sb.append("isCaretListenerInstalled=").append(isCaretListenerInstalled);
sb.append(", isTextListenerInstalled=").append(isTextListenerInstalled);
sb.append(", lastKnownClientWindowBounds=").append(lastKnownClientWindowBounds);
sb.append(", updatesAreDeferred=").append(updatesAreDeferred);
sb.append(", hasDeferredUpdates=").append(hasDeferredUpdates);
sb.append(", trackedComponent=").append(trackedComponent == null ? "null" : trackedComponent.get());
sb.append('}');
return sb.toString();
}
/* Implementation details */
private final WeakReference<WLInputMethodZwpTextInputV3> im;
private WeakReference<Component> trackedComponent = null;
private boolean isCaretListenerInstalled = false;
private boolean isTextListenerInstalled = false;
private Rectangle lastKnownClientWindowBounds = null;
private boolean updatesAreDeferred = false;
private boolean hasDeferredUpdates = false;
private WLInputMethodZwpTextInputV3 getOwnerIm() {
assert(EventQueue.isDispatchThread());
final WLInputMethodZwpTextInputV3 thisImStrong;
if (this.im == null) {
thisImStrong = null;
} else {
thisImStrong = this.im.get();
}
if (thisImStrong == null) {
stopTrackingCurrentComponent();
}
return thisImStrong;
}
private void updateNotify() {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest(String.format("updateNotify(): this=%s.", this), new Throwable("Stacktrace"));
}
if (getTrackedComponentIfTracking() == null) return;
if (updatesAreDeferred) {
hasDeferredUpdates = true;
return;
}
hasDeferredUpdates = false;
final var imToNotify = getOwnerIm();
if (imToNotify != null) {
imToNotify.wlUpdateCursorRectangle(false);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
/** Content hint is a bitmask to allow to modify the behavior of the text input */
enum ContentHint {
/** no special behavior */
NONE (0x0),
/** suggest word completions */
COMPLETION (0x1),
/** suggest word corrections */
SPELLCHECK (0x2),
/** switch to uppercase letters at the start of a sentence */
AUTO_CAPITALIZATION(0x4),
/** prefer lowercase letters */
LOWERCASE (0x8),
/** prefer uppercase letters */
UPPERCASE (0x10),
/** prefer casing for titles and headings (can be language dependent) */
TITLECASE (0x20),
/** characters should be hidden */
HIDDEN_TEXT (0x40),
/** typed text should not be stored */
SENSITIVE_DATA (0x80),
/** just Latin characters should be entered */
LATIN (0x100),
/** the text input is multiline */
MULTILINE (0x200);
public final int intMask;
ContentHint(int intMask) {
this.intMask = intMask;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
/**
* The content purpose allows to specify the primary purpose of a text input.
* This allows an input method to show special purpose input panels with extra characters or to disallow some characters.
*/
enum ContentPurpose {
/** default input, allowing all characters */
NORMAL (0),
/** allow only alphabetic characters */
ALPHA (1),
/** allow only digits */
DIGITS (2),
/** input a number (including decimal separator and sign) */
NUMBER (3),
/** input a phone number */
PHONE (4),
/** input an URL */
URL (5),
/** input an email address */
EMAIL (6),
/** input a name of a person */
NAME (7),
/** input a password (combine with sensitive_data hint) */
PASSWORD(8),
/** input is a numeric password (combine with sensitive_data hint) */
PIN (9),
/** input a date */
DATE (10),
/** input a time */
TIME (11),
/** input a date and time */
DATETIME(12),
/** input for a terminal */
TERMINAL(13);
public final int intValue;
ContentPurpose(int intValue) {
this.intValue = intValue;
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.util.Arrays;
import java.util.Objects;
/**
* This class accumulates changes received as
* {@code zwp_text_input_v3::preedit_string}, {@code zwp_text_input_v3::commit_string} events until
* a {@code zwp_text_input_v3::done} event is received.
*/
final class IncomingChanges
{
public IncomingChanges updatePreeditString(byte[] newPreeditStringUtf8, int newPreeditStringCursorBeginUtf8Byte, int newPreeditStringCursorEndUtf8Byte) {
this.doUpdatePreeditString = true;
this.newPreeditStringUtf8 = newPreeditStringUtf8;
this.newPreeditStringCursorBeginUtf8Byte = newPreeditStringCursorBeginUtf8Byte;
this.newPreeditStringCursorEndUtf8Byte = newPreeditStringCursorEndUtf8Byte;
this.cachedResultPreeditString = null;
return this;
}
/**
* @return {@code null} if there are no changes in the preedit string
* (i.e. {@link #updatePreeditString(byte[], int, int)} hasn't been called);
* an instance of JavaPreeditString otherwise.
* @see JavaPreeditString
*/
public JavaPreeditString getPreeditString() {
if (cachedResultPreeditString != null) {
return cachedResultPreeditString;
}
cachedResultPreeditString = doUpdatePreeditString
? JavaPreeditString.fromWaylandPreeditString(newPreeditStringUtf8, newPreeditStringCursorBeginUtf8Byte, newPreeditStringCursorEndUtf8Byte)
: null;
return cachedResultPreeditString;
}
public IncomingChanges updateCommitString(byte[] newCommitStringUtf8) {
this.doUpdateCommitString = true;
this.newCommitStringUtf8 = newCommitStringUtf8;
this.cachedResultCommitString = null;
return this;
}
/**
* @return {@code null} if there are no changes in the commit string
* (i.e. {@link #updateCommitString(byte[])} hasn't been called);
* an instance of JavaCommitString otherwise.
* @see JavaCommitString
*/
public JavaCommitString getCommitString() {
if (cachedResultCommitString != null) {
return cachedResultCommitString;
}
cachedResultCommitString = doUpdateCommitString
? JavaCommitString.fromWaylandCommitString(newCommitStringUtf8)
: null;
return cachedResultCommitString;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
IncomingChanges that = (IncomingChanges) o;
return doUpdatePreeditString == that.doUpdatePreeditString &&
newPreeditStringCursorBeginUtf8Byte == that.newPreeditStringCursorBeginUtf8Byte &&
newPreeditStringCursorEndUtf8Byte == that.newPreeditStringCursorEndUtf8Byte &&
doUpdateCommitString == that.doUpdateCommitString &&
Arrays.equals(newPreeditStringUtf8, that.newPreeditStringUtf8) &&
Arrays.equals(newCommitStringUtf8, that.newCommitStringUtf8);
}
@Override
public int hashCode() {
return Objects.hash(
doUpdatePreeditString,
Arrays.hashCode(newPreeditStringUtf8),
newPreeditStringCursorBeginUtf8Byte,
newPreeditStringCursorEndUtf8Byte,
doUpdateCommitString,
Arrays.hashCode(newCommitStringUtf8)
);
}
// zwp_text_input_v3::preedit_string
private boolean doUpdatePreeditString = false;
private byte[] newPreeditStringUtf8 = null;
private int newPreeditStringCursorBeginUtf8Byte = 0;
private int newPreeditStringCursorEndUtf8Byte = 0;
private JavaPreeditString cachedResultPreeditString = null;
// zwp_text_input_v3::commit_string
private boolean doUpdateCommitString = false;
private byte[] newCommitStringUtf8 = null;
private JavaCommitString cachedResultCommitString = null;
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.awt.Rectangle;
import java.util.Objects;
/**
* This class encapsulates the entire state of an input context represented by an instance of {@code zwp_text_input_v3}.
*
* @see StateOfEnabled
*/
final class InputContextState {
/** pointer to a native context {@code zwp_text_input_v3} */
public final long nativeContextPtr;
public InputContextState(long nativeContextPtr) {
assert(nativeContextPtr != 0);
this.nativeContextPtr = nativeContextPtr;
}
/** @return 0 if the input context hasn't entered a surface yet. Otherwise, the native pointer to the surface. */
public long getCurrentWlSurfacePtr() {
return currentWlSurfacePtr;
}
public void setCurrentWlSurfacePtr(long currentWlSurfacePtr) {
this.currentWlSurfacePtr = currentWlSurfacePtr;
}
/**
* Notifies the InputContext that a set of changes has been sent and committed to the compositor
* via a {@code zwp_text_input_v3::commit} request. The InputContext reacts by incrementing its commit counter.
*
* @param changes represents the set of changes that have been sent and followed by a 'commit' request.
* Must not be {@code null} (but can be empty, which means only the 'commit' request has been issued).
*
* @return a new instance of {@link OutgoingBeingCommittedChanges} consisting of
* the passed changes and the new value of the commit counter.
*
* @throws NullPointerException if {@code changes} is {@code null}.
*
* @see OutgoingChanges
*/
public OutgoingBeingCommittedChanges syncWithCommittedOutgoingChanges(final OutgoingChanges changes) {
Objects.requireNonNull(changes, "changes");
// zwp_text_input_v3::done natively uses uint32_t for the serial,
// so it can't get greater than 0xFFFFFFFF.
this.commitCounter = (this.commitCounter + 1) % 0x100000000L;
return new OutgoingBeingCommittedChanges(changes, this.commitCounter);
}
public long getCommitCounter() {
return commitCounter;
}
/**
* This class represents the extended state of an {@code InputContextState} that only exists when the context
* is enabled.
*
* @param textChangeCause the property set via a {@code zwp_text_input_v3::set_text_change_cause} request. Must not be {@code null}.
* @param contentHint the property set via a {@code zwp_text_input_v3::set_content_type} request.
* @param contentPurpose the property set via a {@code zwp_text_input_v3::set_content_type} request. Must not be {@code null}.
* @param cursorRectangle the property set via a {@code zwp_text_input_v3::set_cursor_rectangle} request.
* {@code null} means "the text input does not support describing the cursor area".
*/
public record StateOfEnabled(
// zwp_text_input_v3::set_text_change_cause
ChangeCause textChangeCause,
// zwp_text_input_v3::set_content_type.hint
int contentHint,
// zwp_text_input_v3::set_content_type.purpose
ContentPurpose contentPurpose,
// zwp_text_input_v3::set_cursor_rectangle
Rectangle cursorRectangle
) {
public StateOfEnabled {
Objects.requireNonNull(textChangeCause, "textChangeCause");
Objects.requireNonNull(contentPurpose, "contentPurpose");
}
}
public StateOfEnabled getCurrentStateOfEnabled() {
return stateOfEnabled;
}
public boolean isEnabled() {
return getCurrentStateOfEnabled() != null;
}
/**
* NB: if you want to call setEnabledState(null), consider using {@code wlHandleContextGotDisabled()} of
* the owning {@link WLInputMethodZwpTextInputV3}.
*
* @param newState {@code null} to mark the InputContext as disabled,
* otherwise the InputContext will be marked as enabled and having the state as
* specified in the parameter.
*/
public void setEnabledState(StateOfEnabled newState) {
this.stateOfEnabled = newState;
}
public void syncWithAppliedIncomingChanges(final JavaPreeditString appliedPreeditString, final JavaCommitString appliedCommitString, final long doneSerial) {
this.latestAppliedPreeditString = Objects.requireNonNull(appliedPreeditString, "appliedPreeditString");
this.latestAppliedCommitString = Objects.requireNonNull(appliedCommitString, "appliedCommitString");
this.latestDoneSerial = doneSerial;
}
public JavaPreeditString getLatestAppliedPreeditString() {
return latestAppliedPreeditString;
}
public JavaCommitString getLatestAppliedCommitString() {
return latestAppliedCommitString;
}
public long getLatestDoneSerial() {
return latestDoneSerial;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(512);
sb.append("InputContextState@").append(System.identityHashCode(this));
sb.append('{');
sb.append("nativeContextPtr=0x").append(Long.toHexString(nativeContextPtr));
sb.append(", currentWlSurfacePtr=0x").append(Long.toHexString(currentWlSurfacePtr));
sb.append(", commitCounter=").append(commitCounter);
sb.append(", latestDoneSerial=").append(latestDoneSerial);
sb.append(", stateOfEnabled=").append(stateOfEnabled);
sb.append(", latestAppliedPreeditString=").append(latestAppliedPreeditString);
sb.append(", latestAppliedCommitString=").append(latestAppliedCommitString);
sb.append('}');
return sb.toString();
}
// zwp_text_input_v3::enter.surface / zwp_text_input_v3::leave.surface
private long currentWlSurfacePtr = 0;
// zwp_text_input_v3::commit
/**
* How many times changes to this context have been committed (through {@code zwp_text_input_v3::commit}).
* Essentially, it means the most actual version of the context's state.
*/
private long commitCounter = 0;
// zwp_text_input_v3::done.serial
/**
* The {@code serial} parameter of the latest {@code zwp_text_input_v3::done} event received.
* Essentially, it means the latest version of the context's state known/confirmed by the compositor.
*/
private long latestDoneSerial = 0;
/** {@code null} if the InputContextState is disabled. */
private StateOfEnabled stateOfEnabled = null;
/**
* The latest preedit string applied as a result of the latest {@code zwp_text_input_v3::done} event received.
* Must never be {@code null} ; if a {@code zwp_text_input_v3::done} event wasn't preceded by a
* {@code zwp_text_input_v3::preedit_string} event, the field should be set to {@link PropertiesInitials#PREEDIT_STRING}.
*/
private JavaPreeditString latestAppliedPreeditString = PropertiesInitials.PREEDIT_STRING;
/**
* The latest commit string applied as a result of the latest {@code zwp_text_input_v3::done} event received.
* Must never be {@code null} ; if a {@code zwp_text_input_v3::done} event wasn't preceded by a
* {@code zwp_text_input_v3::commit_string} event, the field should be set to {@link PropertiesInitials#COMMIT_STRING}.
*/
private JavaCommitString latestAppliedCommitString = PropertiesInitials.COMMIT_STRING;
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.util.Objects;
record JavaCommitString(String text) {
public JavaCommitString {
Objects.requireNonNull(text, "text");
}
public static final JavaCommitString EMPTY = new JavaCommitString("");
/** Never returns {@code null}. */
public static JavaCommitString fromWaylandCommitString(byte[] utf8Bytes) {
return new JavaCommitString(Utilities.utf8BytesToJavaString(utf8Bytes));
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.util.Objects;
/**
* This class represents the result of a conversion of a UTF-8 preedit string received in a
* {@code zwp_text_input_v3::preedit_string} event to a Java UTF-16 string.
* If {@link #cursorBeginCodeUnit} and/or {@link #cursorEndCodeUnit} point at UTF-16 surrogate pairs,
* they're guaranteed to point at the very beginning of them as long as {@link #fromWaylandPreeditString} is
* used to perform the conversion.
* <p>
* {@link #fromWaylandPreeditString} never returns {@code null}.
* <p>
* See the specification of {@code zwp_text_input_v3::preedit_string} event for more info about
* cursor_begin, cursor_end values.
*
* @param text The preedit text string. Mustn't be {@code null} (use an empty string instead).
* @param cursorBeginCodeUnit UTF-16 equivalent of {@code preedit_string.cursor_begin}.
* @param cursorEndCodeUnit UTF-16 equivalent of {@code preedit_string.cursor_end}.
* It's not explicitly stated in the protocol specification, but it seems to be a valid
* situation when cursor_end < cursor_begin, which means
* the highlight extends to the right from the caret
* (e.g., when the text gets selected with Shift + Left Arrow).
*/
record JavaPreeditString(String text, int cursorBeginCodeUnit, int cursorEndCodeUnit) {
public JavaPreeditString {
Objects.requireNonNull(text, "text");
}
public static final JavaPreeditString EMPTY = new JavaPreeditString("", 0, 0);
public static final JavaPreeditString EMPTY_NO_CARET = new JavaPreeditString("", -1, -1);
public static JavaPreeditString fromWaylandPreeditString(
final byte[] utf8Bytes,
final int cursorBeginUtf8Byte,
final int cursorEndUtf8Byte
) {
// Java's UTF-8 -> UTF-16 conversion doesn't like trailing NUL codepoints, so let's trim them
final int utf8BytesWithoutNulLength = Utilities.getLengthOfUtf8BytesWithoutTrailingNULs(utf8Bytes);
// cursorBeginUtf8Byte, cursorEndUtf8Byte normalized relatively to the valid values range.
final int fixedCursorBeginUtf8Byte;
final int fixedCursorEndUtf8Byte;
if (cursorBeginUtf8Byte < 0 || cursorEndUtf8Byte < 0) {
fixedCursorBeginUtf8Byte = fixedCursorEndUtf8Byte = -1;
} else {
// 0 <= cursorBeginUtf8Byte <= fixedCursorBeginUtf8Byte <= utf8BytesWithoutNulLength
fixedCursorBeginUtf8Byte = Math.min(cursorBeginUtf8Byte, utf8BytesWithoutNulLength);
// 0 <= cursorEndUtf8Byte <= fixedCursorEndUtf8Byte <= utf8BytesWithoutNulLength
fixedCursorEndUtf8Byte = Math.min(cursorEndUtf8Byte, utf8BytesWithoutNulLength);
}
final var resultText = Utilities.utf8BytesToJavaString(utf8Bytes, 0, utf8BytesWithoutNulLength);
if (fixedCursorBeginUtf8Byte < 0 || fixedCursorEndUtf8Byte < 0) {
return new JavaPreeditString(resultText, -1, -1);
}
if (resultText == null) {
assert(fixedCursorBeginUtf8Byte == 0);
assert(fixedCursorEndUtf8Byte == 0);
return JavaPreeditString.EMPTY;
}
final String javaPrefixBeforeCursorBegin = (fixedCursorBeginUtf8Byte == 0)
? ""
: Utilities.utf8BytesToJavaString(utf8Bytes, 0, fixedCursorBeginUtf8Byte);
final String javaPrefixBeforeCursorEnd = (fixedCursorEndUtf8Byte == 0)
? ""
: Utilities.utf8BytesToJavaString(utf8Bytes, 0, fixedCursorEndUtf8Byte);
return new JavaPreeditString(
resultText,
javaPrefixBeforeCursorBegin.length(),
javaPrefixBeforeCursorEnd.length()
);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.util.Objects;
/**
* This class is intended to keep changes after they get committed and until they actually get applied.
*
* @param changeSet changes that have been sent and committed to the compositor,
* but not yet confirmed by it (via a {@code zwp_text_input_v3::done} event).
* Must not be {@code null}.
* @param commitCounter the number of times a {@code zwp_text_input_v3::commit} request has been issued to
* the corresponding {@link InputContextState}.
*
* @see OutgoingChanges
*/
record OutgoingBeingCommittedChanges(OutgoingChanges changeSet, long commitCounter) {
public OutgoingBeingCommittedChanges {
Objects.requireNonNull(changeSet, "changeSet");
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.awt.Rectangle;
import java.util.Objects;
/**
* This class is intended to accumulate changes for an {@link InputContextState} until
* they're sent via the set of requests
* {@code zwp_text_input_v3::enable}, {@code zwp_text_input_v3::disable}, {@code zwp_text_input_v3::set_*}
* and commited via {@code zwp_text_input_v3::commit}.
* <p>
* The reason of having to accumulate changes instead of applying them as soon as they appear is the following
* part of the {@code zpw_text_input_v3::done(serial)} event specification:
* {@code
* When the client receives a done event with a serial different than the number of past commit requests,
* it must proceed with evaluating and applying the changes as normal, except it should not change the
* current state of the zwp_text_input_v3 object. All pending state requests [...]
* on the zwp_text_input_v3 object should be sent and committed after receiving a
* zwp_text_input_v3.done event with a matching serial.
* }
*<p>
* All the properties this class includes are nullable where {@code null} means absence of this property change.
* In other words, if a property is null, the corresponding {@code zwp_text_input_v3::set_...} shouldn't be
* called when processing this instance of OutgoingChanges.
* <p>
* The modifier methods return {@code this} for method chaining.
*/
final class OutgoingChanges
{
// zwp_text_input_v3::enable / zwp_text_input_v3::disable
private Boolean newEnabled = null;
// zwp_text_input_v3::set_text_change_cause
private ChangeCause newTextChangeCause = null;
// zwp_text_input_v3::set_content_type
private Integer newContentTypeHint = null;
private ContentPurpose newContentTypePurpose = null;
// zwp_text_input_v3::set_cursor_rectangle
private Rectangle newCursorRectangle = null;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(256);
sb.append("OutgoingChanges@").append(System.identityHashCode(this));
sb.append('[');
sb.append("newEnabled=").append(newEnabled);
sb.append(", newTextChangeCause=").append(newTextChangeCause);
sb.append(", newContentTypeHint=").append(newContentTypeHint);
sb.append(", newContentTypePurpose=").append(newContentTypePurpose);
sb.append(", newCursorRectangle=").append(newCursorRectangle);
sb.append(']');
return sb.toString();
}
public OutgoingChanges setEnabledState(Boolean newEnabled) {
this.newEnabled = newEnabled;
return this;
}
public Boolean getEnabledState() { return newEnabled; }
public OutgoingChanges setTextChangeCause(ChangeCause newTextChangeCause) {
this.newTextChangeCause = newTextChangeCause;
return this;
}
public ChangeCause getTextChangeCause() { return newTextChangeCause; }
/**
* Both parameters have to be {@code null} or not null simultaneously.
*
* @throws NullPointerException if one of the parameters is {@code null} while the other one is not.
*/
public OutgoingChanges setContentType(Integer newContentTypeHint, ContentPurpose newContentTypePurpose) {
if (newContentTypeHint == null && newContentTypePurpose == null) {
this.newContentTypeHint = null;
this.newContentTypePurpose = null;
} else {
final var contentHintAllMask =
ContentHint.NONE.intMask |
ContentHint.COMPLETION.intMask |
ContentHint.SPELLCHECK.intMask |
ContentHint.AUTO_CAPITALIZATION.intMask |
ContentHint.LOWERCASE.intMask |
ContentHint.UPPERCASE.intMask |
ContentHint.TITLECASE.intMask |
ContentHint.HIDDEN_TEXT.intMask |
ContentHint.SENSITIVE_DATA.intMask |
ContentHint.LATIN.intMask |
ContentHint.MULTILINE.intMask;
if ( (Objects.requireNonNull(newContentTypeHint, "newContentTypeHint") & ~contentHintAllMask) != 0 ) {
throw new IllegalArgumentException(String.format("newContentTypeHint=%d has invalid bits set", newContentTypeHint));
}
this.newContentTypeHint = newContentTypeHint;
this.newContentTypePurpose = Objects.requireNonNull(newContentTypePurpose, "newContentTypePurpose");
}
return this;
}
public Integer getContentTypeHint() { return newContentTypeHint; }
public ContentPurpose getContentTypePurpose() { return newContentTypePurpose; }
public OutgoingChanges setCursorRectangle(Rectangle newCursorRectangle) {
this.newCursorRectangle = newCursorRectangle;
return this;
}
public Rectangle getCursorRectangle() { return newCursorRectangle; }
public OutgoingChanges appendChangesFrom(OutgoingChanges src) {
if (src == null) return this;
if (getTextChangeCause() == null) {
setTextChangeCause(src.getTextChangeCause());
}
if (getContentTypeHint() == null) {
setContentType(src.getContentTypeHint(), src.getContentTypePurpose());
}
if (getCursorRectangle() == null) {
setCursorRectangle(src.getCursorRectangle());
}
return this;
}
public boolean isEmpty() {
return (getEnabledState() == null && getTextChangeCause() == null && getContentTypeHint() == null && getCursorRectangle() == null);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.awt.Rectangle;
interface PropertiesInitials {
/** {@code zwp_text_input_v3::set_text_change_cause} */
ChangeCause TEXT_CHANGE_CAUSE = ChangeCause.INPUT_METHOD;
/** {@code zwp_text_input_v3::set_content_type} (hint) */
int CONTENT_HINT = ContentHint.NONE.intMask;
/** {@code zwp_text_input_v3::set_content_type} (purpose) */
ContentPurpose CONTENT_PURPOSE = ContentPurpose.NORMAL;
/**
* {@code zwp_text_input_v3::set_cursor_rectangle}.
* <p>
* The initial values describing a cursor rectangle are empty.
* That means the text input does not support describing the cursor area.
* If the empty values get applied, subsequent attempts to change them may have no effect.
*/
Rectangle CURSOR_RECTANGLE = null;
/** {@code zwp_text_input_v3::preedit_string} */
JavaPreeditString PREEDIT_STRING = new JavaPreeditString("", 0, 0);
/** {@code zwp_text_input_v3::commit_string} */
JavaCommitString COMMIT_STRING = new JavaCommitString("");
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import java.nio.charset.StandardCharsets;
interface Utilities {
static int getLengthOfUtf8BytesWithoutTrailingNULs(final byte[] utf8Bytes) {
int lastNonNulIndex = (utf8Bytes == null) ? -1 : utf8Bytes.length - 1;
for (; lastNonNulIndex >= 0; --lastNonNulIndex) {
if (utf8Bytes[lastNonNulIndex] != 0) {
break;
}
}
return (lastNonNulIndex < 0) ? 0 : lastNonNulIndex + 1;
}
static String utf8BytesToJavaString(final byte[] utf8Bytes) {
if (utf8Bytes == null) {
return "";
}
return utf8BytesToJavaString(
utf8Bytes,
0,
// Java's UTF-8 -> UTF-16 conversion doesn't like trailing NUL codepoints, so let's trim them
getLengthOfUtf8BytesWithoutTrailingNULs(utf8Bytes)
);
}
static String utf8BytesToJavaString(final byte[] utf8Bytes, final int offset, final int length) {
return utf8Bytes == null ? "" : new String(utf8Bytes, offset, length, StandardCharsets.UTF_8);
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.wl.im.text_input_unstable_v3;
import sun.awt.wl.WLToolkit;
import sun.util.logging.PlatformLogger;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.im.spi.InputMethod;
import java.awt.im.spi.InputMethodDescriptor;
import java.util.Locale;
public final class WLInputMethodDescriptorZwpTextInputV3 implements InputMethodDescriptor {
// See java.text.MessageFormat for the formatting syntax
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.im.text_input_unstable_v3.WLInputMethodDescriptorZwpTextInputV3");
public static boolean isAvailableOnPlatform() {
return initAndGetIsAvailableOnPlatform();
}
public static WLInputMethodDescriptorZwpTextInputV3 getInstanceIfAvailableOnPlatform() {
if (!isAvailableOnPlatform()) {
return null;
}
return new WLInputMethodDescriptorZwpTextInputV3();
}
/* java.awt.im.spi.InputMethodDescriptor methods section */
@Override
public Locale[] getAvailableLocales() throws AWTException {
ensureIsAvailableOnPlatform();
return getAvailableLocalesInternal();
}
@Override
public boolean hasDynamicLocaleList() {
// Since the return value of {@link #getAvailableLocales()} doesn't currently change over time,
// it doesn't make sense to return true here.
return false;
}
@Override
public String getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage) {
assert isAvailableOnPlatform();
// This is how it's implemented in all other Toolkits.
//
// We ignore the input locale.
// When displaying for the default locale, rely on the localized AWT properties;
// for any other locale, fall back to English.
String name = "System Input Methods";
if (Locale.getDefault().equals(displayLanguage)) {
name = Toolkit.getProperty("AWT.HostInputMethodDisplayName", name);
}
return name;
}
@Override
public Image getInputMethodIcon(Locale inputLocale) {
return null;
}
@Override
public InputMethod createInputMethod() throws Exception {
// NB: we should avoid returning null from this method because the calling code isn't really ready to get null
ensureIsAvailableOnPlatform();
final var result = new WLInputMethodZwpTextInputV3();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("createInputMethod(): result={0}.", result);
}
return result;
}
/* java.lang.Object methods section */
@Override
public String toString() {
return String.format("WLInputMethodDescriptorZwpTextInputV3@%d", System.identityHashCode(this));
}
/* Implementation details section */
/** Used as the return value for {@link #getAvailableLocales()}. */
private volatile static Locale toolkitStartupLocale = null;
private volatile static Boolean isAvailableOnPlatform = null;
static Locale[] getAvailableLocalesInternal() {
// This is how it's implemented in XToolkit.
//
// A better implementation would be obtaining all currently installed and enabled input sources
// (like on GNOME Settings -> Keyboard -> Input Sources) and mapping them to locales.
// However, there seem no universal Wayland API for that, so it seems can't be implemented reliably.
//
// So leaving as is at the moment.
//
// TODO: research how to implement this better along with {@link #hasDynamicLocaleList}
return new Locale[]{ (Locale)initAndGetToolkitStartupLocale().clone() };
}
private static Locale initAndGetToolkitStartupLocale() {
if (toolkitStartupLocale == null) {
synchronized (WLInputMethodDescriptorZwpTextInputV3.class) {
if (toolkitStartupLocale == null) {
toolkitStartupLocale = WLToolkit.getStartupLocale();
}
}
}
if (log.isLoggable(PlatformLogger.Level.CONFIG)) {
log.config("initAndGetToolkitStartupLocale(): toolkitStartupLocale={0}.", toolkitStartupLocale);
}
return toolkitStartupLocale;
}
private static boolean initAndGetIsAvailableOnPlatform() {
if (isAvailableOnPlatform == null) {
synchronized (WLInputMethodDescriptorZwpTextInputV3.class) {
try {
if (isAvailableOnPlatform == null) {
isAvailableOnPlatform = checkIfAvailableOnPlatform();
}
} catch (Exception err) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Failed to check whether the IM protocol is supported on the system", err);
}
isAvailableOnPlatform = false;
}
}
}
if (log.isLoggable(PlatformLogger.Level.CONFIG)) {
log.config("initAndGetIsAvailableOnPlatform(): isAvailableOnPlatform={0}.", isAvailableOnPlatform);
}
return isAvailableOnPlatform;
}
private static void ensureIsAvailableOnPlatform() throws AWTException {
if (!isAvailableOnPlatform()) {
throw new AWTException("sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3 is not supported on this system");
}
}
private WLInputMethodDescriptorZwpTextInputV3() {
assert isAvailableOnPlatform();
initAndGetToolkitStartupLocale();
}
/* JNI downcalls section */
/**
* This method checks if {@link WLInputMethodZwpTextInputV3} can function on this system.
* Basically, it means the Wayland compositor supports a minimal sufficient subset of the required protocols
* (currently the set only includes the "text-input-unstable-v3" protocol).
*
* @return true if {@link WLInputMethodZwpTextInputV3} can function on this system, false otherwise.
* @see <a href="https://wayland.app/protocols/text-input-unstable-v3">text-input-unstable-v3</a>
*/
private static native boolean checkIfAvailableOnPlatform();
}

View File

@@ -26,6 +26,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <pthread.h>
#include "JNIUtilities.h"
#include "WLToolkit.h"
@@ -42,6 +43,9 @@ enum DataTransferProtocol
DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION = sun_awt_wl_WLDataDevice_DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION,
};
struct DataSource;
struct DataOffer;
// native part of WLDataDevice, one instance per seat
// seat's wl_data_device and zwp_primary_selection_device_v1 have user pointers to this struct
struct DataDevice
@@ -53,12 +57,20 @@ struct DataDevice
struct wl_event_queue *dataSourceQueue;
struct wl_data_device *wlDataDevice;
struct zwp_primary_selection_device_v1 *zwpPrimarySelectionDevice;
pthread_mutex_t sourceDelMutex;
struct DataSource* sourceDelQueue;
pthread_mutex_t offerDelMutex;
struct DataOffer* offerDelQueue;
};
// native part of WLDataSource, remains alive until WLDataSource.destroy() is called
// pointer to this structure is the wl_data_source's (zwp_primary_selection_source_v1's) user pointer
struct DataSource
{
struct DataDevice* dataDevice;
enum DataTransferProtocol protocol;
// global reference to the corresponding WLDataSource object
// destroyed in WLDataSource.destroy()
@@ -74,12 +86,16 @@ struct DataSource
struct wl_surface* dragIcon;
struct wl_buffer* dragIconBuffer;
struct DataSource* nextDel;
};
// native part of WLDataOffer, remains alive until WLDataOffer.destroy() is called
// pointer to this structure is the wl_data_offer's (zwp_primary_selection_offer_v1's) user pointer
struct DataOffer
{
struct DataDevice* dataDevice;
enum DataTransferProtocol protocol;
// global reference to the corresponding WLDataOffer object
// destroyed in WLDataOffer.destroy()
@@ -92,6 +108,8 @@ struct DataOffer
struct wl_data_offer *wlDataOffer;
struct zwp_primary_selection_offer_v1 *zwpPrimarySelectionOffer;
};
struct DataOffer* nextDel;
};
// Java refs
@@ -313,10 +331,13 @@ static struct DataOffer *
DataOffer_create(struct DataDevice *dataDevice, enum DataTransferProtocol protocol, void *waylandObject)
{
struct DataOffer *offer = calloc(1, sizeof(struct DataOffer));
if (offer == NULL) {
return NULL;
}
offer->dataDevice = dataDevice;
JNIEnv *env = getEnv();
assert(env != NULL);
@@ -431,6 +452,68 @@ DataOffer_callSelectionHandler(struct DataDevice *dataDevice, struct DataOffer *
EXCEPTION_CLEAR(env);
}
static void
DataDevice_drainSourceDeletionQueue(struct DataDevice *dataDevice, JNIEnv* env) {
pthread_mutex_lock(&dataDevice->sourceDelMutex);
struct DataSource* source = dataDevice->sourceDelQueue;
while (source != NULL) {
if (source->protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
wl_data_source_destroy(source->wlDataSource);
} else if (source->protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
zwp_primary_selection_source_v1_destroy(source->zwpPrimarySelectionSource);
}
if (source->dragIconBuffer) {
wl_buffer_destroy(source->dragIconBuffer);
}
if (source->dragIcon) {
wl_surface_destroy(source->dragIcon);
}
if (source->javaObject != NULL) {
(*env)->DeleteGlobalRef(env, source->javaObject);
}
struct DataSource* next = source->nextDel;
free(source);
source = next;
}
dataDevice->sourceDelQueue = NULL;
pthread_mutex_unlock(&dataDevice->sourceDelMutex);
}
static void
DataDevice_drainOfferDeletionQueue(struct DataDevice *dataDevice, JNIEnv* env) {
pthread_mutex_lock(&dataDevice->offerDelMutex);
struct DataOffer* offer = dataDevice->offerDelQueue;
while (offer != NULL) {
if (offer->protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
wl_data_offer_destroy(offer->wlDataOffer);
} else if (offer->protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
zwp_primary_selection_offer_v1_destroy(offer->zwpPrimarySelectionOffer);
}
if (offer->javaObject != NULL) {
(*env)->DeleteGlobalRef(env, offer->javaObject);
}
struct DataOffer* next = offer->nextDel;
free(offer);
offer = next;
}
dataDevice->offerDelQueue = NULL;
pthread_mutex_unlock(&dataDevice->offerDelMutex);
}
// Event handlers
static void
@@ -793,6 +876,9 @@ Java_sun_awt_wl_WLDataDevice_initNative(JNIEnv *env, jobject obj, jlong wlSeatPt
return 0;
}
pthread_mutex_init(&dataDevice->sourceDelMutex, NULL);
pthread_mutex_init(&dataDevice->offerDelMutex, NULL);
dataDevice->javaObject = (*env)->NewGlobalRef(env, obj);
if ((*env)->ExceptionCheck(env)) {
goto error_cleanup;
@@ -834,7 +920,10 @@ Java_sun_awt_wl_WLDataDevice_initNative(JNIEnv *env, jobject obj, jlong wlSeatPt
return ptr_to_jlong(dataDevice);
error_cleanup:
error_cleanup:
pthread_mutex_destroy(&dataDevice->sourceDelMutex);
pthread_mutex_destroy(&dataDevice->offerDelMutex);
if (dataDevice->dataSourceQueue != NULL) {
wl_event_queue_destroy(dataDevice->dataSourceQueue);
}
@@ -881,6 +970,7 @@ Java_sun_awt_wl_WLDataDevice_dispatchDataSourceQueueImpl(JNIEnv *env, jclass cla
assert(dataDevice != NULL);
while (wl_display_dispatch_queue(wl_display, dataDevice->dataSourceQueue) != -1) {
DataDevice_drainSourceDeletionQueue(dataDevice, env);
}
}
@@ -924,27 +1014,36 @@ Java_sun_awt_wl_WLDataDevice_startDragImpl(JNIEnv *env, jclass clazz, jlong data
}
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLDataDevice_performDeletionsOnEDTImpl(JNIEnv *env, jclass clazz, jlong dataDeviceNativePtr) {
struct DataDevice *dataDevice = jlong_to_ptr(dataDeviceNativePtr);
assert(dataDevice != NULL);
DataDevice_drainOfferDeletionQueue(dataDevice, env);
}
JNIEXPORT jlong JNICALL
Java_sun_awt_wl_WLDataSource_initNative(JNIEnv *env, jobject javaObject, jlong dataDeviceNativePtr, jint protocol)
{
struct DataDevice *dataDevice = jlong_to_ptr(dataDeviceNativePtr);
assert(dataDevice != NULL);
struct DataSource *dataSource = calloc(1, sizeof(struct DataSource));
struct DataSource *source = calloc(1, sizeof(struct DataSource));
if (dataSource == NULL) {
if (source == NULL) {
JNU_ThrowOutOfMemoryError(env, "Failed to allocate DataSource");
return 0;
}
source->dataDevice = dataDevice;
// cleaned up in WLDataSource.destroy()
dataSource->javaObject = (*env)->NewGlobalRef(env, javaObject);
source->javaObject = (*env)->NewGlobalRef(env, javaObject);
if ((*env)->ExceptionCheck(env)) {
free(dataSource);
free(source);
return 0;
}
if (dataSource->javaObject == NULL) {
free(dataSource);
if (source->javaObject == NULL) {
free(source);
JNU_ThrowInternalError(env, "Failed to create a reference to WLDataSource");
return 0;
}
@@ -953,7 +1052,7 @@ Java_sun_awt_wl_WLDataSource_initNative(JNIEnv *env, jobject javaObject, jlong d
protocol = DATA_TRANSFER_PROTOCOL_WAYLAND;
}
dataSource->protocol = protocol;
source->protocol = protocol;
if (protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
// To avoid race conditions when setting the dispatch queue,
@@ -970,14 +1069,14 @@ Java_sun_awt_wl_WLDataSource_initNative(JNIEnv *env, jobject javaObject, jlong d
}
if (wlDataSource == NULL) {
free(dataSource);
free(source);
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland error creating wl_data_source proxy");
return 0;
}
dataSource->wlDataSource = wlDataSource;
source->wlDataSource = wlDataSource;
wl_data_source_add_listener(wlDataSource, &wl_data_source_listener, dataSource);
wl_data_source_add_listener(wlDataSource, &wl_data_source_listener, source);
}
if (protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
@@ -991,18 +1090,18 @@ Java_sun_awt_wl_WLDataSource_initNative(JNIEnv *env, jobject javaObject, jlong d
}
if (zwpPrimarySelectionSource == NULL) {
free(dataSource);
free(source);
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland error creating zwp_primary_selection_source_v1 proxy");
return 0;
}
dataSource->zwpPrimarySelectionSource = zwpPrimarySelectionSource;
source->zwpPrimarySelectionSource = zwpPrimarySelectionSource;
zwp_primary_selection_source_v1_add_listener(zwpPrimarySelectionSource,
&zwp_primary_selection_source_v1_listener, dataSource);
&zwp_primary_selection_source_v1_listener, source);
}
return ptr_to_jlong(dataSource);
return ptr_to_jlong(source);
}
JNIEXPORT void JNICALL
@@ -1026,26 +1125,13 @@ Java_sun_awt_wl_WLDataSource_destroyImpl(JNIEnv *env, jclass clazz, jlong native
return;
}
if (source->protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
wl_data_source_destroy(source->wlDataSource);
} else if (source->protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
zwp_primary_selection_source_v1_destroy(source->zwpPrimarySelectionSource);
}
assert(source->dataDevice != NULL);
struct DataDevice* dataDevice = source->dataDevice;
if (source->dragIconBuffer) {
wl_buffer_destroy(source->dragIconBuffer);
}
if (source->dragIcon) {
wl_surface_destroy(source->dragIcon);
}
if (source->javaObject != NULL) {
(*env)->DeleteGlobalRef(env, source->javaObject);
source->javaObject = NULL;
}
free(source);
pthread_mutex_lock(&dataDevice->sourceDelMutex);
source->nextDel = dataDevice->sourceDelQueue;
dataDevice->sourceDelQueue = source;
pthread_mutex_unlock(&dataDevice->sourceDelMutex);
}
JNIEXPORT void JNICALL
@@ -1132,18 +1218,13 @@ Java_sun_awt_wl_WLDataOffer_destroyImpl(JNIEnv *env, jclass clazz, jlong nativeP
return;
}
if (offer->protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
wl_data_offer_destroy(offer->wlDataOffer);
} else if (offer->protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
zwp_primary_selection_offer_v1_destroy(offer->zwpPrimarySelectionOffer);
}
assert(offer->dataDevice != NULL);
struct DataDevice* dataDevice = offer->dataDevice;
if (offer->javaObject != NULL) {
(*env)->DeleteGlobalRef(env, offer->javaObject);
offer->javaObject = NULL;
}
free(offer);
pthread_mutex_lock(&dataDevice->offerDelMutex);
offer->nextDel = dataDevice->offerDelQueue;
dataDevice->offerDelQueue = offer;
pthread_mutex_unlock(&dataDevice->offerDelMutex);
}
JNIEXPORT void JNICALL

View File

@@ -90,6 +90,8 @@ struct wl_data_device_manager *wl_ddm = NULL;
struct zwp_primary_selection_device_manager_v1 *zwp_selection_dm = NULL; // optional, check for NULL before use
struct zxdg_output_manager_v1 *zxdg_output_manager_v1 = NULL; // optional, check for NULL before use
struct zwp_text_input_manager_v3 *zwp_text_input_manager = NULL; // optional, check for NULL before use
static uint32_t num_of_outstanding_sync = 0;
// This group of definitions corresponds to declarations from awt.h
@@ -621,6 +623,14 @@ registry_global(void *data, struct wl_registry *wl_registry,
WLOutputXdgOutputManagerBecameAvailable();
process_new_listener_before_end_of_init();
}
} else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
// If the requested version is higher than the provided one by the compositor,
// the event loop may shut down as soon as it gets launched (wl_display_dispatch will return -1),
// so let's protect from this since the component being obtained is not vital for work.
const uint32_t versionToBind = 1;
if (versionToBind <= version) {
zwp_text_input_manager = wl_registry_bind(wl_registry, name, &zwp_text_input_manager_v3_interface, versionToBind);
}
}
#ifdef WAKEFIELD_ROBOT

View File

@@ -31,7 +31,7 @@
#include "primary-selection-unstable-v1.h"
#include "viewporter.h"
#include "relative-pointer-unstable-v1.h"
#include "text-input-unstable-v3.h"
#include "jvm_md.h"
#include "jni_util.h"
@@ -69,6 +69,8 @@ extern struct wl_data_device_manager *wl_ddm;
extern struct zwp_primary_selection_device_manager_v1 *zwp_selection_dm; // optional, check for NULL before use
extern struct zxdg_output_manager_v1 *zxdg_output_manager_v1; // optional, check for NULL before use
extern struct zwp_relative_pointer_manager_v1* relative_pointer_manager;
extern struct zwp_text_input_manager_v3 *zwp_text_input_manager; // optional, check for NULL before use
JNIEnv *getEnv();
int wlFlushToServer(JNIEnv* env);

View File

@@ -0,0 +1,687 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.
*/
#include "sun_awt_wl_im_text_input_unstable_v3_WLInputMethodDescriptorZwpTextInputV3.h"
#include "sun_awt_wl_im_text_input_unstable_v3_WLInputMethodZwpTextInputV3.h"
#include "WLToolkit.h" // wl_seat, zwp_text_input_*, uint[...]_t, int[...]_t
#include "JNIUtilities.h"
#include <stdbool.h> // bool, true, false
#include <string.h> // memset, strlen
#include <stdlib.h> // malloc, free
#include <assert.h> // assert
static bool checkIfTheImplementationIsAvailable() {
return (zwp_text_input_manager == NULL) ? false : true;
}
static struct {
jclass wlInputMethodClass;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onEnter`
jmethodID mID_tiOnEnter;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onLeave`
jmethodID mID_tiOnLeave;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onPreeditString`
jmethodID mID_tiOnPreeditString;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onCommitString`
jmethodID mID_tiOnCommitString;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onDeleteSurroundingText`
jmethodID mID_tiOnDeleteSurroundingText;
/// `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3#zwp_text_input_v3_onDone`
jmethodID mID_tiOnDone;
} jniIDs = {0};
// ================================================= IMContext section ================================================
static void IMContext_zwp_text_input_v3_onEnter(void*, struct zwp_text_input_v3*, struct wl_surface*);
static void IMContext_zwp_text_input_v3_onLeave(void*, struct zwp_text_input_v3*, struct wl_surface*);
static void IMContext_zwp_text_input_v3_onPreeditString(void*, struct zwp_text_input_v3*, const char*, int32_t, int32_t);
static void IMContext_zwp_text_input_v3_onCommitString(void*, struct zwp_text_input_v3*, const char*);
static void IMContext_zwp_text_input_v3_onDeleteSurroundingText(void*, struct zwp_text_input_v3*, uint32_t, uint32_t);
static void IMContext_zwp_text_input_v3_onDone(void*, struct zwp_text_input_v3*, uint32_t);
static const struct zwp_text_input_v3_listener IMContext_zwp_text_input_v3_listener = {
.enter = &IMContext_zwp_text_input_v3_onEnter,
.leave = &IMContext_zwp_text_input_v3_onLeave,
.preedit_string = &IMContext_zwp_text_input_v3_onPreeditString,
.commit_string = &IMContext_zwp_text_input_v3_onCommitString,
.delete_surrounding_text = &IMContext_zwp_text_input_v3_onDeleteSurroundingText,
.done = &IMContext_zwp_text_input_v3_onDone,
};
/**
* The native-side counterpart of `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3`.
* On Java side these contexts are created and destroyed through
* `WLInputMethod#createNativeContext` and `WLInputMethod#destroyNativeContext` respectively.
*
* `IMContext` and `WLInputMethodZwpTextInputV3` are related in a 1:1 ratio - an instance of `WLInputMethodZwpTextInputV3` holds no more than 1
* instance of `IMContext` and an instance of `IMContext` only belongs to 1 instance of `WLInputMethodZwpTextInputV3`.
*/
struct IMContext {
/// A global reference to the instance of `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3` owning this instance of `IMContext`.
jobject wlInputMethodOwner;
/// Represents an input context for the entire `text-input-unstable-v3` protocol.
struct zwp_text_input_v3 *textInput;
};
/**
* Creates and fully initializes an instance of `struct IMContext`.
*
* @param wlInputMethodOwnerRefToCopy a reference to the owning instance of `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3`.
* NB: the reference will be copied via `NewGlobalRef` and no longer used.
* @return `null` if it has failed to create or completely initialize a new instance.
* In this case a corresponding exception of class `java.awt.AWTException` or of an unchecked exception class
* will be raised in @p env
*/
static struct IMContext* IMContext_Create(JNIEnv * const env, jobject wlInputMethodOwnerRefToCopy) {
struct wl_seat * const wlSeat = wl_seat;
struct zwp_text_input_manager_v3 * const textInputManager = zwp_text_input_manager;
struct IMContext *result = NULL;
jobject wlInputMethodOwner = NULL;
struct zwp_text_input_v3 *textInput = NULL;
if (wlSeat == NULL) {
JNU_ThrowByName(env, "java/awt/AWTException", "IMContext_Create: no wl_seat is available");
goto failure;
}
if (textInputManager == NULL) {
JNU_ThrowNullPointerException(env, "IMContext_Create: textInputManager is NULL");
goto failure;
}
wlInputMethodOwner = (*env)->NewGlobalRef(env, wlInputMethodOwnerRefToCopy);
if (wlInputMethodOwner == NULL) {
if ((*env)->ExceptionCheck(env) == JNI_FALSE) {
JNU_ThrowOutOfMemoryError(env, "IMContext_Create: NewGlobalRef(wlInputMethodOwnerRefToCopy) failed");
}
goto failure;
}
wlInputMethodOwnerRefToCopy = NULL; // To avoid misusages
result = malloc(sizeof(struct IMContext));
if (result == NULL) {
JNU_ThrowOutOfMemoryError(env, "IMContext_Create: malloc(sizeof(struct IMContext)) failed");
goto failure;
}
textInput = zwp_text_input_manager_v3_get_text_input(textInputManager, wlSeat);
if (textInput == NULL) {
JNU_ThrowByName(env, "java/awt/AWTException", "IMContext_Create: failed to obtain a new instance of zwp_text_input_v3");
goto failure;
}
// WLToolkit dispatches (almost) all native Wayland events on EDT, not on its thread.
// If it didn't, the callbacks being set here might be called even before this function finishes, hence even before
// the constructor of `sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3` finishes (because the constructor gets called on the
// EDT rather than on the toolkit thread).
// In that case we would have to take it into account while implementing the callbacks and
// `WLInputMethodZwpTextInputV3` class in general.
zwp_text_input_v3_add_listener(textInput, &IMContext_zwp_text_input_v3_listener, result);
(void)memset(result, 0, sizeof(struct IMContext));
result->wlInputMethodOwner = wlInputMethodOwner;
result->textInput = textInput;
return result;
failure:
if (textInput != NULL) {
zwp_text_input_v3_destroy(textInput);
textInput = NULL;
}
if (result != NULL) {
free(result);
result = NULL;
}
if (wlInputMethodOwner != NULL) {
(*env)->DeleteGlobalRef(env, wlInputMethodOwner);
wlInputMethodOwner = NULL;
}
return NULL;
}
/// Destroys the context previously created by IMContext_Create
static void IMContext_Destroy(JNIEnv * const env, struct IMContext * const imContext) {
assert(env != NULL);
assert(imContext != NULL);
if (imContext->textInput != NULL) {
zwp_text_input_v3_destroy(imContext->textInput);
imContext->textInput = NULL;
}
if (imContext->wlInputMethodOwner != NULL) {
(*env)->DeleteGlobalRef(env, imContext->wlInputMethodOwner);
imContext->wlInputMethodOwner = NULL;
}
free(imContext);
}
// The IMContext_zwp_text_input_v3_on* callbacks are supposed to be as a thin bridge to
// `WLInputMethodZwpTextInputV3`'s JNI upcalls as possible in terms of contained logic.
// Generally they should only invoke the corresponding upcalls with the received parameters.
//
// Exceptions after making JNI upcalls to WLInputMethodZwpTextInputV3 are checked (via JNU_CHECK_EXCEPTION),
// but not suppressed on a purpose: all the corresponding Java methods already handles any java.lang.Exception.
// So if an exception leaves any of those methods, it's something really strange and it's better to let WLToolkit
// get to know about it rather than log and try to continue the normal path.
// The checks are just made to suppress -Xcheck:jni warnings.
static void IMContext_zwp_text_input_v3_onEnter(
void * const ctx,
struct zwp_text_input_v3 * const textInput,
struct wl_surface * const surface
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
(*env)->CallVoidMethod(env, imContext->wlInputMethodOwner, jniIDs.mID_tiOnEnter, ptr_to_jlong(surface));
JNU_CHECK_EXCEPTION(env);
}
static void IMContext_zwp_text_input_v3_onLeave(
void * const ctx,
struct zwp_text_input_v3 * const textInput,
struct wl_surface * const surface
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
(*env)->CallVoidMethod(env, imContext->wlInputMethodOwner, jniIDs.mID_tiOnLeave, ptr_to_jlong(surface));
JNU_CHECK_EXCEPTION(env);
}
/**
* Converts a UTF-8 string to a Java byte array, throwing an OutOfMemoryError if the allocation fails. Another kind
* of exceptions may also appear, according to the implementation of 'NewByteArray' and 'SetByteArrayRegion'.
* Regardless of the returned value, always check 'env->ExceptionCheck()' after each call of this function.
*
* @param utf8Str UTF-8 string to convert.
* @param utf8StrSizeInBytes size of the UTF-8 string in bytes, or a negative value to ask the function to
* calculate it manually.
* @param env JNI environment. Mustn't be NULL.
* @param oomMessage message to use in the OutOfMemoryError exception if it appears. Mustn't be NULL.
*
* @return a local JNI reference to a Java byte array or NULL if 'utf8Str' is NULL,
* an exception occurred,
* or 'NewByteArray' returned NULL for some other reason.
*/
static jbyteArray utf8StrToJByteArrayOrThrowOOM(
const char * const utf8Str,
ssize_t utf8StrSizeInBytes,
JNIEnv * const env,
const char * const oomMessage
) {
jbyteArray result = NULL;
assert(env != NULL);
assert(oomMessage != NULL);
if (utf8Str == NULL) {
return NULL;
}
if (utf8StrSizeInBytes < 0) {
// Let's believe there's a trailing NUL codepoint (otherwise we can't calculate the string's size), and
// there are no NUL codepoints in the middle, though it's possible in general for UTF-8.
utf8StrSizeInBytes = (ssize_t)(strlen(utf8Str) + 1);
}
result = (*env)->NewByteArray(env, (jsize)utf8StrSizeInBytes);
if (result == NULL) {
if ((*env)->ExceptionCheck(env) == JNI_FALSE) {
JNU_ThrowOutOfMemoryError(env, oomMessage);
}
} else {
(*env)->SetByteArrayRegion(
env,
result,
0,
(jsize)utf8StrSizeInBytes,
(const jbyte*)utf8Str
);
}
return result;
}
static void IMContext_zwp_text_input_v3_onPreeditString(
void * const ctx,
struct zwp_text_input_v3 * const textInput,
const char * const preeditStringUtf8,
const int32_t cursorBeginUtf8Byte,
const int32_t cursorEndUtf8Byte
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
jbyteArray preeditStringUtf8Bytes = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
// may still be NULL
preeditStringUtf8Bytes = utf8StrToJByteArrayOrThrowOOM(
preeditStringUtf8,
// the zwp_text_input_v3::preedit_string event doesn't provide the length or size of the string separately,
// asking the function to manually calculate it.
-1,
env,
"IMContext_zwp_text_input_v3_onPreeditString: failed to allocate a new Java byte array"
);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
return;
}
(*env)->CallVoidMethod(
env,
imContext->wlInputMethodOwner,
jniIDs.mID_tiOnPreeditString,
preeditStringUtf8Bytes,
(jint)cursorBeginUtf8Byte,
(jint)cursorEndUtf8Byte
);
JNU_CHECK_EXCEPTION(env);
}
static void IMContext_zwp_text_input_v3_onCommitString(
void * const ctx,
struct zwp_text_input_v3 * const textInput,
const char * const commitStringUtf8
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
jbyteArray commitStringUtf8Bytes = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
// may still be NULL
commitStringUtf8Bytes = utf8StrToJByteArrayOrThrowOOM(
commitStringUtf8,
// the zwp_text_input_v3::commit_string event doesn't provide the length or size of the string separately,
// asking the function to manually calculate it.
-1,
env,
"IMContext_zwp_text_input_v3_onCommitString: failed to allocate a new Java byte array"
);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
return;
}
(*env)->CallVoidMethod(env, imContext->wlInputMethodOwner, jniIDs.mID_tiOnCommitString, commitStringUtf8Bytes);
JNU_CHECK_EXCEPTION(env);
}
static void IMContext_zwp_text_input_v3_onDeleteSurroundingText(
void * const ctx,
struct zwp_text_input_v3 * const textInput,
const uint32_t numberOfUtf8BytesBeforeToDelete,
const uint32_t numberOfUtf8BytesAfterToDelete
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
return;
}
(*env)->CallVoidMethod(
env,
imContext->wlInputMethodOwner,
jniIDs.mID_tiOnDeleteSurroundingText,
(jlong)numberOfUtf8BytesBeforeToDelete,
(jlong)numberOfUtf8BytesAfterToDelete
);
JNU_CHECK_EXCEPTION(env);
}
static void IMContext_zwp_text_input_v3_onDone(
void *const ctx,
struct zwp_text_input_v3 * const textInput,
const uint32_t serial
) {
const struct IMContext * const imContext = ctx;
JNIEnv *env = NULL;
if (imContext == NULL) {
return;
}
env = getEnv();
if (env == NULL) {
return;
}
(*env)->CallVoidMethod(env, imContext->wlInputMethodOwner, jniIDs.mID_tiOnDone, (jlong)serial);
JNU_CHECK_EXCEPTION(env);
}
// ============================================= END of IMContext section =============================================
// =============================================== JNI downcalls section ==============================================
JNIEXPORT jboolean JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodDescriptorZwpTextInputV3_checkIfAvailableOnPlatform(JNIEnv * const env, const jclass clazz) {
return checkIfTheImplementationIsAvailable() ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_initIDs(JNIEnv * const env, const jclass clazz) {
CHECK_NULL_THROW_OOME(
env,
jniIDs.wlInputMethodClass = (*env)->NewGlobalRef(env, clazz),
"Allocation of a global reference to sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3 class failed"
);
jniIDs.mID_tiOnEnter =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onEnter", "(J)V");
if (jniIDs.mID_tiOnEnter == NULL) {
// DeleteGlobalRef is one of the few JNI functions that are safe to call while there's a pending exception
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
jniIDs.mID_tiOnLeave =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onLeave", "(J)V");
if (jniIDs.mID_tiOnLeave == NULL) {
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
jniIDs.mID_tiOnPreeditString =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onPreeditString", "([BII)V");
if (jniIDs.mID_tiOnPreeditString == NULL) {
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
jniIDs.mID_tiOnCommitString =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onCommitString", "([B)V");
if (jniIDs.mID_tiOnCommitString == NULL) {
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
jniIDs.mID_tiOnDeleteSurroundingText =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onDeleteSurroundingText", "(JJ)V");
if (jniIDs.mID_tiOnDeleteSurroundingText == NULL) {
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
jniIDs.mID_tiOnDone =
(*env)->GetMethodID(env, jniIDs.wlInputMethodClass, "zwp_text_input_v3_onDone", "(J)V");
if (jniIDs.mID_tiOnDone == NULL) {
(*env)->DeleteGlobalRef(env, jniIDs.wlInputMethodClass);
(void)memset(&jniIDs, 0, sizeof(jniIDs));
return;
}
}
JNIEXPORT jlong JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_createNativeContext(JNIEnv * const env, const jobject self) {
struct IMContext *result = NULL;
if (!checkIfTheImplementationIsAvailable()) {
JNU_ThrowByName(env, "java/awt/AWTException", "sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3 is not supported on this system");
return 0;
}
result = IMContext_Create(env, self);
return ptr_to_jlong(result);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_disposeNativeContext(
JNIEnv * const env,
const jclass clazz,
const jlong contextPtr
) {
struct IMContext *imContext = jlong_to_ptr(contextPtr);
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
IMContext_Destroy(env, imContext);
imContext = NULL;
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1enable(
JNIEnv * const env,
const jobject self,
const jlong contextPtr
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_enable(textInput);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1disable(
JNIEnv * const env,
const jobject self,
const jlong contextPtr
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_disable(textInput);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1set_1cursor_1rectangle(
JNIEnv * const env,
const jobject self,
const jlong contextPtr,
const jint surfaceLocalX,
const jint surfaceLocalY,
const jint width,
const jint height
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_set_cursor_rectangle(
textInput,
(int32_t)surfaceLocalX,
(int32_t)surfaceLocalY,
(int32_t)width,
(int32_t)height
);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1set_1content_1type(
JNIEnv * const env,
const jobject self,
const jlong contextPtr,
const jint hint,
const jint purpose
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_set_content_type(textInput, (uint32_t)hint, (uint32_t)purpose);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1set_1text_1change_1cause(
JNIEnv * const env,
const jobject self,
const jlong contextPtr,
const jint changeCause
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_set_text_change_cause(textInput, (uint32_t)changeCause);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_im_text_1input_1unstable_1v3_WLInputMethodZwpTextInputV3_zwp_1text_1input_1v3_1commit(
JNIEnv * const env,
const jobject self,
const jlong contextPtr
) {
const struct IMContext * const imContext = jlong_to_ptr(contextPtr);
struct zwp_text_input_v3 *textInput = NULL;
if (imContext == NULL) {
JNU_ThrowNullPointerException(env, "contextPtr");
return;
}
textInput = imContext->textInput;
if (textInput == NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "textInput == NULL");
return;
}
zwp_text_input_v3_commit(textInput);
}
// =========================================== END of JNI downcalls section ===========================================

View File

@@ -33,6 +33,7 @@
#ifndef _AIX
#include "screencast_pipewire.h"
#include "java_awt_event_KeyEvent.h"
struct pw_buffer *(*fp_pw_stream_dequeue_buffer)(struct pw_stream *stream);
const char * (*fp_pw_stream_state_as_string)(enum pw_stream_state state);
@@ -1016,6 +1017,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
isGtkMainThread = gtk->g_main_context_is_owner(gtk->g_main_context_default());
DEBUG_SCREENCAST(
@@ -1121,7 +1123,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
DEBUG_SCREENCAST("moving mouse to\n\t%d %d\n\twith token |%s|\n", jx, jy, token);
@@ -1151,6 +1153,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, mouse pressing %d\n", result, buttons)
@@ -1178,6 +1181,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, mouse wheel %d\n", result, jWheelAmt)
@@ -1194,6 +1198,24 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
return result ? RESULT_OK : pw.pwFd;
}
static int getNumpadKey(jint jkey) {
switch (jkey) {
case java_awt_event_KeyEvent_VK_NUMPAD0: return XK_KP_Insert;
case java_awt_event_KeyEvent_VK_NUMPAD1: return XK_KP_End;
case java_awt_event_KeyEvent_VK_NUMPAD2: return XK_KP_Down;
case java_awt_event_KeyEvent_VK_NUMPAD3: return XK_KP_Page_Down;
case java_awt_event_KeyEvent_VK_NUMPAD4: return XK_KP_Left;
case java_awt_event_KeyEvent_VK_NUMPAD5: return XK_KP_Begin;
case java_awt_event_KeyEvent_VK_NUMPAD6: return XK_KP_Right;
case java_awt_event_KeyEvent_VK_NUMPAD7: return XK_KP_Home;
case java_awt_event_KeyEvent_VK_NUMPAD8: return XK_KP_Up;
case java_awt_event_KeyEvent_VK_NUMPAD9: return XK_KP_Prior;
case java_awt_event_KeyEvent_VK_DECIMAL:
case java_awt_event_KeyEvent_VK_SEPARATOR: return XK_KP_Delete;
default: return 0;
}
}
/*
* Class: sun_awt_screencast_ScreencastHelper
* Method: remoteDesktopKeyImpl
@@ -1202,17 +1224,21 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl
(JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) {
AWT_LOCK();
int key = awt_getX11KeySym(jkey);
AWT_UNLOCK();
int key = getNumpadKey(jkey);
if (!key) {
AWT_LOCK();
key = awt_getX11KeySym(jkey);
AWT_UNLOCK();
}
if (key == NoSymbol) {
if (key == NoSymbol || (*env)->ExceptionCheck(env)) {
return RESULT_ERROR;
}
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, key %d -> %d isPress %b\n", result, jkey, key, isPress)

View File

@@ -41,7 +41,7 @@ import org.xml.sax.SAXNotSupportedException;
/**
* @author Rajiv Mordani
* @author Edwin Goei
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
/** These are DocumentBuilderFactory attributes not DOM attributes */
@@ -59,11 +59,24 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
XMLSecurityManager fSecurityManager;
XMLSecurityPropertyManager fSecurityPropertyMgr;
/**
* Creates a new {@code DocumentBuilderFactory} instance.
*/
public DocumentBuilderFactoryImpl() {
this(null, null);
}
/**
* Creates a new {@code DocumentBuilderFactory} instance with a {@code XMLSecurityManager}
* and {@code XMLSecurityPropertyManager}.
* @param xsm the {@code XMLSecurityManager}
* @param xspm the {@code XMLSecurityPropertyManager}
*/
public DocumentBuilderFactoryImpl(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) {
JdkXmlConfig config = JdkXmlConfig.getInstance(false);
// security (property) managers updated with current system properties
fSecurityManager = config.getXMLSecurityManager(true);
fSecurityPropertyMgr = config.getXMLSecurityPropertyManager(true);
fSecurityManager = (xsm == null) ? config.getXMLSecurityManager(true) : xsm;
fSecurityPropertyMgr = (xspm == null) ? config.getXMLSecurityPropertyManager(true) : xspm;
}
/**

View File

@@ -35,7 +35,7 @@ import jdk.xml.internal.*;
*
* @author Ramesh Mandava
*
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class XPathFactoryImpl extends XPathFactory {
@@ -72,6 +72,7 @@ public class XPathFactoryImpl extends XPathFactory {
* The XML security manager
*/
private XMLSecurityManager _xmlSecMgr;
private XMLSecurityPropertyManager _xmlSecPropMgr;
/**
* javax.xml.xpath.XPathFactory implementation.
@@ -80,6 +81,7 @@ public class XPathFactoryImpl extends XPathFactory {
JdkXmlConfig config = JdkXmlConfig.getInstance(false);
_xmlSecMgr = config.getXMLSecurityManager(true);
_featureManager = config.getXMLFeatures(true);
_xmlSecPropMgr = config.getXMLSecurityPropertyManager(true);
}
/**
@@ -129,7 +131,7 @@ public class XPathFactoryImpl extends XPathFactory {
*/
public javax.xml.xpath.XPath newXPath() {
return new XPathImpl(xPathVariableResolver, xPathFunctionResolver,
!_isNotSecureProcessing, _featureManager, _xmlSecMgr);
!_isNotSecureProcessing, _featureManager, _xmlSecMgr, _xmlSecPropMgr);
}
/**
@@ -183,6 +185,7 @@ public class XPathFactoryImpl extends XPathFactory {
if (value && _featureManager != null) {
_featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
JdkProperty.State.FSP, false);
_xmlSecMgr.setSecureProcessing(value);
}
// all done processing feature
@@ -338,8 +341,7 @@ public class XPathFactoryImpl extends XPathFactory {
throw new NullPointerException(fmsg);
}
if (_xmlSecMgr != null &&
_xmlSecMgr.setLimit(name, JdkProperty.State.APIPROPERTY, value)) {
if (JdkXmlUtils.setProperty(_xmlSecMgr, _xmlSecPropMgr, name, value)) {
return;
}

View File

@@ -36,6 +36,7 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlConfig;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@@ -50,7 +51,7 @@ import org.xml.sax.InputSource;
* New methods: evaluateExpression
* Refactored to share code with XPathExpressionImpl.
*
* @LastModified: May 2025
* @LastModified: June 2025
*/
public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
@@ -62,12 +63,13 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false,
JdkXmlConfig.getInstance(false).getXMLFeatures(false),
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false));
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
}
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, JdkXmlFeatures featureManager,
XMLSecurityManager xmlSecMgr) {
XMLSecurityManager xmlSecMgr, XMLSecurityPropertyManager xmlSecPropMgr) {
this.origVariableResolver = this.variableResolver = vr;
this.origFunctionResolver = this.functionResolver = fr;
this.featureSecureProcessing = featureSecureProcessing;
@@ -75,6 +77,7 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
overrideDefaultParser = featureManager.getFeature(
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
this.xmlSecMgr = xmlSecMgr;
this.xmlSecPropMgr = xmlSecPropMgr;
}

View File

@@ -31,6 +31,7 @@ import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -44,6 +45,7 @@ import javax.xml.xpath.XPathVariableResolver;
import jdk.xml.internal.JdkXmlFeatures;
import jdk.xml.internal.JdkXmlUtils;
import jdk.xml.internal.XMLSecurityManager;
import jdk.xml.internal.XMLSecurityPropertyManager;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeIterator;
@@ -54,7 +56,7 @@ import org.xml.sax.SAXException;
* This class contains several utility methods used by XPathImpl and
* XPathExpressionImpl
*
* @LastModified: Apr 2025
* @LastModified: June 2025
*/
class XPathImplUtil {
XPathFunctionResolver functionResolver;
@@ -67,6 +69,7 @@ class XPathImplUtil {
boolean featureSecureProcessing = false;
JdkXmlFeatures featureManager;
XMLSecurityManager xmlSecMgr;
XMLSecurityPropertyManager xmlSecPropMgr;
/**
* Evaluate an XPath context using the internal XPath engine
@@ -128,7 +131,12 @@ class XPathImplUtil {
//
// so we really have to create a fresh DocumentBuilder every time we need one
// - KK
DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser);
DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(
overrideDefaultParser, xmlSecMgr, xmlSecPropMgr);
if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
xmlSecMgr.isSecureProcessing());
}
return dbf.newDocumentBuilder().parse(source);
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new XPathExpressionException (e);

View File

@@ -445,6 +445,20 @@ public class JdkXmlUtils {
* @return a DocumentBuilderFactory instance.
*/
public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) {
return getDOMFactory(overrideDefaultParser, null, null);
}
/**
* {@return a DocumentBuilderFactory instance}
*
* @param overrideDefaultParser a flag indicating whether the system-default
* implementation may be overridden. If the system property of the
* DOM factory ID is set, override is always allowed.
* @param xsm XMLSecurityManager
* @param xspm XMLSecurityPropertyManager
*/
public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser,
XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) {
boolean override = overrideDefaultParser;
String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID);
@@ -453,7 +467,7 @@ public class JdkXmlUtils {
}
DocumentBuilderFactory dbf
= !override
? new DocumentBuilderFactoryImpl()
? new DocumentBuilderFactoryImpl(xsm, xspm)
: DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
// false is the default setting. This step here is for compatibility

View File

@@ -244,6 +244,12 @@ public final class XMLSecurityManager implements Cloneable {
*/
boolean secureProcessing;
/**
* Flag indicating the secure processing is set explicitly through factories'
* setFeature method and then the setSecureProcessing method
*/
boolean secureProcessingSet;
/**
* States that determine if properties are set explicitly
*/
@@ -340,6 +346,7 @@ public final class XMLSecurityManager implements Cloneable {
* Setting FEATURE_SECURE_PROCESSING explicitly
*/
public void setSecureProcessing(boolean secure) {
secureProcessingSet = true;
secureProcessing = secure;
for (Limit limit : Limit.values()) {
if (secure) {
@@ -358,6 +365,15 @@ public final class XMLSecurityManager implements Cloneable {
return secureProcessing;
}
/**
* Returns the state indicating whether the Secure Processing is set explicitly,
* via factories' setFeature and then this class' setSecureProcessing method.
* @return the state indicating whether the Secure Processing is set explicitly
*/
public boolean isSecureProcessingSet() {
return secureProcessingSet;
}
/**
* Finds a limit's new name with the given property name.
* @param propertyName the property name specified

View File

@@ -91,6 +91,8 @@ requires.properties= \
vm.compiler1.enabled \
vm.compiler2.enabled \
vm.musl \
vm.asan \
vm.ubsan \
vm.flagless \
container.support \
systemd.support \

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2025, Institute of Software, Chinese Academy of Sciences.
* All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package compiler.c2.irTests.stringopts;
import compiler.lib.ir_framework.*;
/**
* @test
* @bug 8359270
* @requires vm.debug == true & vm.compiler2.enabled
* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64"
* @summary C2: alignment check should consider base offset when emitting arraycopy runtime call.
* @library /test/lib /
* @run driver compiler.c2.irTests.stringopts.TestArrayCopySelect
*/
public class TestArrayCopySelect {
public static final String input_strU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28";
public static final char[] input_arrU = new char[] {'\u0f21', '\u0f22', '\u0f23', '\u0f24',
'\u0f25', '\u0f26', '\u0f27', '\u0f28'};
public static String output_strU;
public static char[] output_arrU;
public static void main(String[] args) {
TestFramework.runWithFlags("-XX:-UseCompactObjectHeaders",
"-XX:-CompactStrings",
"-XX:CompileCommand=inline,java.lang.StringBuilder::toString",
"-XX:CompileCommand=inline,java.lang.StringUTF16::getChars",
"-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes");
TestFramework.runWithFlags("-XX:+UseCompactObjectHeaders",
"-XX:-CompactStrings",
"-XX:CompileCommand=inline,java.lang.StringBuilder::toString",
"-XX:CompileCommand=inline,java.lang.StringUTF16::getChars",
"-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes");
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "false"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"})
static void testSBToStringAligned() {
// Exercise the StringBuilder.toString API
StringBuilder sb = new StringBuilder(input_strU);
output_strU = sb.append(input_strU).toString();
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "true"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"})
static void testSBToStringUnAligned() {
// Exercise the StringBuilder.toString API
StringBuilder sb = new StringBuilder(input_strU);
output_strU = sb.append(input_strU).toString();
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "false"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"})
static void testStrUGetCharsAligned() {
// Exercise the StringUTF16.getChars API
output_arrU = input_strU.toCharArray();
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "true"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"})
static void testStrUGetCharsUnAligned() {
// Exercise the StringUTF16.getChars API
output_arrU = input_strU.toCharArray();
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "false"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"})
static void testStrUtoBytesAligned() {
// Exercise the StringUTF16.toBytes API
output_strU = String.valueOf(input_arrU);
}
@Test
@Warmup(10000)
@IR(applyIf = {"UseCompactObjectHeaders", "true"},
counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"})
static void testStrUtoBytesUnAligned() {
// Exercise the StringUTF16.toBytes API
output_strU = String.valueOf(input_arrU);
}
}

View File

@@ -141,7 +141,7 @@ public class BasicIntOpTest extends VectorizationTestRunner {
}
@Test
@IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"},
@IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "zvbb", "true"},
counts = {IRNode.POPCOUNT_VI, ">0"})
public int[] vectorPopCount() {
int[] res = new int[SIZE];

View File

@@ -31,6 +31,8 @@ package gc.arguments;
* @library /test/lib
* @library /
* @requires vm.bits == "64"
* @comment ulimit clashes with the memory requirements of ASAN
* @requires !vm.asan
* @requires os.family == "linux"
* @requires vm.gc != "Z"
* @requires vm.opt.UseCompressedOops == null

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package gc.z;
/*
* @test id=ZFakeNUMA
* @requires vm.gc.Z & vm.debug
* @library / /test/lib
* @summary Test ZGC graceful failure when a commit fails (with ZFakeNUMA)
* @run driver gc.z.TestCommitFailure -XX:ZFakeNUMA=16
*/
import jdk.test.lib.process.ProcessTools;
import static gc.testlibrary.Allocation.blackHole;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TestCommitFailure {
static final int K = 1024;
static final int M = 1024 * K;
static final int XMS = 128 * M;
static final int XMX = 512 * M;
static class Test {
static final int LARGE_ALLOC = 256 * M;
static final int SMALL_GARBAGE = 256 * M;
static final int SMALL_LIVE = 128 * M;
// Allocates at least totalLive bytes of objects and add them to list.
static void allocLive(List<Object> list, int totalLive) {
final int largePageAllocationSize = 6 * M;
for (int live = 0; live < totalLive; live += largePageAllocationSize) {
list.add(new byte[largePageAllocationSize - K]);
}
}
// Allocates at least totalGarbage bytes of garbage large pages.
static void allocGarbage(int totalGarbage) {
final int largePageAllocationSize = 6 * M;
for (int garbage = 0; garbage < totalGarbage; garbage += largePageAllocationSize) {
blackHole(new byte[largePageAllocationSize - K]);
}
}
public static void main(String[] args) {
final var list = new ArrayList<Object>();
try {
// Fill heap with small live objects
allocLive(list, SMALL_LIVE);
// Fill with small garbage objects
allocGarbage(SMALL_GARBAGE);
// Allocate large objects where commit fails until an OOME is thrown
while (true) {
list.add(new byte[LARGE_ALLOC - K]);
}
} catch (OutOfMemoryError oome) {}
blackHole(list);
}
}
public static void main(String[] args) throws Exception {
final int xmxInM = XMX / M;
final int xmsInM = XMS / M;
final var arguments = new ArrayList(Arrays.asList(args));
arguments.addAll(List.of(
"-XX:+UseZGC",
"-Xlog:gc+init",
"-XX:ZFailLargerCommits=" + XMS,
"-Xms" + xmsInM + "M",
"-Xmx" + xmxInM + "M",
Test.class.getName()));
ProcessTools.executeTestJava(arguments)
.outputTo(System.out)
.errorTo(System.out)
.shouldHaveExitValue(0);
}
}

View File

@@ -58,7 +58,7 @@ gc/stress/gcold/TestGCOldWithShenandoah.java#aggressive JBR-8563 windows-aarch64
# :hotspot_runtime
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#coh_no_cds JBR-6616 windows-aarch64
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#coh_no_cds JBR-6616,JBR-9488 windows-aarch64,macosx-26.0
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#no_coh_cds JBR-6616 windows-aarch64
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#no_coh_no_cds JBR-6616 windows-aarch64
runtime/ErrorHandling/ErrorFileOverwriteTest.java JBR-8524 windows-aarch64
@@ -91,10 +91,10 @@ vmTestbase/jit/misctests/t5/t5.java JBR-8854 linux-aarch64
vmTestbase/jit/misctests/putfield00802/putfield00802.java JBR-8801 linux-aarch64,windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545 windows-aarch64,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8927,JBR-8545 windows-all,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8927,JBR-8545 windows-all,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8927,JBR-8545 windows-all,windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java JBR-8927,JBR-8545 windows-all,windows-x64
#############################################################################

View File

@@ -95,7 +95,6 @@ compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all
compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x
compiler/linkage/TestLinkageErrorInGenerateOopMap.java JBR-8524 windows-aarch64
compiler/loopopts/TestUnreachableInnerLoop.java 8288981 linux-s390x
compiler/rtm/locking/TestRTMAbortRatio.java 8183263 generic-x64,generic-i586
compiler/rtm/locking/TestRTMAbortThreshold.java 8183263 generic-x64,generic-i586
@@ -116,7 +115,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897 aix-ppc64,linux-ppc64le
compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64
compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all
compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all
@@ -152,12 +150,6 @@ gc/TestAllocHumongousFragment.java#aggressive 8298781 generic-all
gc/TestAllocHumongousFragment.java#iu-aggressive 8298781 generic-all
gc/TestAllocHumongousFragment.java#g1 8298781 generic-all
gc/TestAllocHumongousFragment.java#static 8298781 generic-all
gc/TestAlwaysPreTouchBehavior.java#ParallelCollector 8334513 generic-all
gc/TestAlwaysPreTouchBehavior.java#SerialCollector 8334513 generic-all
gc/TestAlwaysPreTouchBehavior.java#Shenandoah 8334513 generic-all
gc/TestAlwaysPreTouchBehavior.java#G1 8334513 generic-all
gc/TestAlwaysPreTouchBehavior.java#Z 8334513 generic-all
gc/TestAlwaysPreTouchBehavior.java#Epsilon 8334513 generic-all
gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all
gc/shenandoah/oom/TestAllocOutOfMemory.java#large 8344312 linux-ppc64le
gc/shenandoah/TestEvilSyncBug.java#generational 8345501 generic-all
@@ -172,7 +164,6 @@ runtime/jni/terminatedThread/TestTerminatedThread.java 8317789 aix-ppc64
runtime/cds/CheckDefaultArchiveFile.java JBR-4227 generic-all
runtime/cds/SharedBaseAddress.java#id2 JBR-9078 windows-aarch64
runtime/cds/SharedBaseAddress.java#id3 JBR-9078 windows-aarch64
runtime/handshake/HandshakeSuspendExitTest.java 8318631 generic-all
runtime/modules/ClassLoaderNoUnnamedModuleTest.java JBR-8516 windows-aarch64
runtime/Monitor/SyncOnValueBasedClassTest.java 8340995,JBR-8517 linux-s390x,windows-aarch64
runtime/os/TestTracePageSizes.java#no-options 8267460 linux-aarch64
@@ -182,7 +173,7 @@ runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64
runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64
runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64
runtime/os/windows/TestAvailableProcessors.java JBR-8182 windows-all
runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433,JBR-7917,JBR-8528 macosx-x64,macosx-all,windows-aarch64
runtime/ErrorHandling/CreateCoredumpOnCrash.java JBR-7917,JBR-8528 macosx-all,windows-aarch64
runtime/Safepoint/TestAbortOnVMOperationTimeout.java JBR-8524 windows-aarch64
runtime/Safepoint/TestAbortVMOnSafepointTimeout.java JBR-8524 windows-aarch64
runtime/StackGuardPages/TestStackGuardPages.java 8303612 linux-all 8293452
@@ -191,7 +182,7 @@ runtime/stringtable/StringTableCorruptionTest.java JBR-8524 windows-aarch64
runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315,JBR-6289 linux-ppc64le,windows-aarch64
runtime/ErrorHandling/TestAbortVmOnException.java JBR-8514 windows-aarch64
runtime/ErrorHandling/UncaughtNativeExceptionTest.java JBR-8515 windows-aarch64
runtime/NMT/CheckForProperDetailStackTrace.java 8347002 linux-all
runtime/NMT/CheckForProperDetailStackTrace.java JBR-8914 linux-all
runtime/NMT/MallocLimitTest.java#compiler-limit-fatal JBR-8524 windows-aarch64
runtime/NMT/MallocLimitTest.java#global-limit-fatal JBR-8524 windows-aarch64
runtime/NMT/MallocLimitTest.java#multi-limit JBR-8524 windows-aarch64
@@ -230,8 +221,6 @@ runtime/cds/TestDefaultArchiveLoading.java#coops_nocoh JBR-6616 windows-aarch64
runtime/cds/TestDefaultArchiveLoading.java#nocoops_nocoh JBR-6616 windows-aarch64
runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java initial_run generic-all
sources/TestNoNULL.java JBR-8419 generic-all
#############################################################################
# :hotspot_serviceability
@@ -349,6 +338,7 @@ vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEa
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545 windows-aarch64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8927,JBR-8545 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8927,JBR-8545 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8927 windows-all
mTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java JBR-8927,JBR-8545 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64

View File

@@ -38,6 +38,8 @@
* @requires os.family != "windows" & os.family != "aix"
* @comment TODO: Decide libjsig support on static JDK with 8351367
* @requires !jdk.static
* @comment loading of the jsig lib does currently not work well with ASAN lib
* @requires !vm.asan
* @library /vmTestbase
* /test/lib
* @run driver TestBreakSignalThreadDump load_libjsig

View File

@@ -29,6 +29,8 @@
* @modules java.base/jdk.internal.misc
* java.management
* @requires os.family == "linux" | os.family == "mac"
* @comment loading of the jsig lib does currently not work well with ASAN lib
* @requires !vm.asan
* @comment TODO: Decide libjsig support on static JDK with 8351367
* @requires !jdk.static
* @run driver XCheckJSig

View File

@@ -36,6 +36,8 @@ import java.util.regex.Pattern;
* @summary Test of diagnostic command System.map
* @library /test/lib
* @requires (os.family == "linux" | os.family == "windows" | os.family == "mac")
* @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements
* @requires !vm.asan
* @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")
* @modules java.base/jdk.internal.misc
* java.compiler

View File

@@ -32,6 +32,8 @@ import jdk.test.lib.process.OutputAnalyzer;
* @summary Test of diagnostic command System.map
* @library /test/lib
* @requires (vm.gc != "Z") & (os.family == "linux" | os.family == "windows" | os.family == "mac")
* @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements
* @requires !vm.asan
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
@@ -47,6 +49,8 @@ import jdk.test.lib.process.OutputAnalyzer;
* @summary Test of diagnostic command System.map using ZGC
* @library /test/lib
* @requires vm.gc.Z & (os.family == "linux" | os.family == "windows" | os.family == "mac")
* @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements
* @requires !vm.asan
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -154,9 +154,9 @@ class contmon01Task implements Runnable {
System.out.println("check #2 done");
System.out.println("notifying main thread");
System.out.println("thread is going to loop while <flag> is true ...");
contmon01.startingBarrier = false;
System.out.println("thread is going to loop while <flag> is true ...");
int i = 0;
int n = 1000;
while (flag) {

View File

@@ -102,6 +102,8 @@ requires.properties= \
vm.cds.write.archived.java.heap \
vm.continuations \
vm.musl \
vm.asan \
vm.ubsan \
vm.debug \
vm.hasSA \
vm.hasJFR \

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,8 @@ import java.util.zip.ZipInputStream;
* @bug 8226346
* @summary Check all output files for absolute path fragments
* @requires !vm.debug
* @comment ASAN keeps the 'unwanted' paths in the binaries because of its build options
* @requires !vm.asan
* @run main/othervm -Xmx900m AbsPathsInImage
*/
public class AbsPathsInImage {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
@test
@bug 5013984
@bug 5013984 8360647
@summary Tests KEY_PRESSED has the same KeyChar as KEY_RELEASED
@key headful
@run main KeyCharTest
@@ -37,7 +37,7 @@ import java.awt.event.MouseEvent;
import java.util.HashMap;
public class KeyCharTest extends Frame implements KeyListener {
HashMap<Integer, Character> transMap = new HashMap();
HashMap<Integer, Character> transMap = new HashMap<>();
public void keyTyped(KeyEvent e){
}
@@ -47,22 +47,35 @@ public class KeyCharTest extends Frame implements KeyListener {
}
public void keyReleased(KeyEvent e){
Object value = transMap.get(e.getKeyCode());
if (value != null && e.getKeyChar() != ((Character)value).charValue()) {
Character value = transMap.get(e.getKeyCode());
if (value != null && e.getKeyChar() != value) {
throw new RuntimeException("Wrong KeyChar on KEY_RELEASED "+
KeyEvent.getKeyText(e.getKeyCode()));
}
}
public void start () {
private void testKeyRange(Robot robot, int start, int end) {
System.out.printf("\nTesting range on %d to %d\n", start, end);
for(int vkey = start; vkey <= end; vkey++) {
try {
robot.keyPress(vkey);
robot.keyRelease(vkey);
System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey);
} catch (RuntimeException ignored) {}
}
robot.delay(100);
}
public void start() throws Exception {
Robot robot = new Robot();
addKeyListener(this);
setLocationRelativeTo(null);
setSize(200, 200);
setVisible(true);
requestFocus();
boolean wasNumlockPressed = false;
try {
Robot robot = new Robot();
robot.setAutoDelay(10);
robot.setAutoWaitForIdle(true);
robot.delay(100);
@@ -72,22 +85,25 @@ public class KeyCharTest extends Frame implements KeyListener {
robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK);
for(int vkey = 0x20; vkey < 0x7F; vkey++) {
try {
robot.keyPress(vkey);
robot.keyRelease(vkey);
System.out.println(KeyEvent.getKeyText(vkey) + " " + vkey);
} catch (RuntimeException e) {
}
}
robot.delay(100);
testKeyRange(robot, 0x20, 0x7E);
// Try again with a different numpad state.
robot.keyPress(KeyEvent.VK_NUM_LOCK);
robot.keyRelease(KeyEvent.VK_NUM_LOCK);
wasNumlockPressed = true;
testKeyRange(robot, KeyEvent.VK_NUMPAD0, KeyEvent.VK_DIVIDE);
} catch(Exception e){
e.printStackTrace();
throw new RuntimeException("Exception while performing Robot actions.");
} finally {
if (wasNumlockPressed) {
robot.keyPress(KeyEvent.VK_NUM_LOCK);
robot.keyRelease(KeyEvent.VK_NUM_LOCK);
}
}
}
public static void main(String[] args) {
public static void main(String[] args) throws Exception {
KeyCharTest test = new KeyCharTest();
try {
test.start();

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8202088 8207152 8217609 8219890 8358819
* @summary Test the localized Japanese calendar names, such as
* the Reiwa Era names (May 1st. 2019-), or the Gan-nen text
* @modules jdk.localedata
* @run junit JapaneseCalendarNameTest
*/
import static java.util.Calendar.*;
import static java.util.Locale.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Locale;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class JapaneseCalendarNameTest {
private static final Calendar c = new Calendar.Builder()
.setCalendarType("japanese")
.setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1)
.build();
private static final Locale JAJPJP = Locale.of("ja", "JP", "JP");
private static final Locale JCAL = Locale.forLanguageTag("ja-u-ca-japanese");
private static Stream<Arguments> reiwaEraNames() {
return Stream.of(
// type, locale, name
Arguments.of(LONG, JAPAN, "令和"),
Arguments.of(LONG, US, "Reiwa"),
Arguments.of(LONG, CHINA, "令和"),
Arguments.of(SHORT, JAPAN, "令和"),
Arguments.of(SHORT, US, "Reiwa"),
Arguments.of(SHORT, CHINA, "令和")
);
}
@ParameterizedTest
@MethodSource("reiwaEraNames")
void testReiwaEraName(int type, Locale locale, String expected) {
assertEquals(expected, c.getDisplayName(ERA, type, locale));
}
private static Stream<Arguments> gannen() {
return Stream.of(
// format,
// formatted text
Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JAJPJP),
"令和元年5月1日水曜日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JCAL),
"令和元年5月1日水曜日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JAJPJP),
"令和元年5月1日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JCAL),
"令和元年5月1日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JAJPJP),
"令和1年5月1日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JCAL),
"令和1年5月1日"),
Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JAJPJP),
"令和1/5/1"),
Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JCAL),
"令和1/5/1")
);
}
@ParameterizedTest
@MethodSource("gannen")
void testGannenFormat(DateFormat df, String expected) {
assertEquals(expected, df.format(c.getTime()));
}
@ParameterizedTest
@MethodSource("gannen")
void testGannenParse(DateFormat df, String formatted) throws ParseException {
assertEquals(c.getTime(), df.parse(formatted));
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8202088 8207152 8217609 8219890
* @summary Test the localized Japanese new era name (May 1st. 2019-)
* is retrieved no matter CLDR provider contains the name or not.
* @modules jdk.localedata
* @run testng JapaneseEraNameTest
*/
import static java.util.Calendar.*;
import static java.util.Locale.*;
import java.util.Calendar;
import java.util.Locale;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@Test
public class JapaneseEraNameTest {
static final Calendar c = new Calendar.Builder()
.setCalendarType("japanese")
.setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1)
.build();
@DataProvider(name="names")
Object[][] names() {
return new Object[][] {
// type, locale, name
{ LONG, JAPAN, "\u4ee4\u548c" },
{ LONG, US, "Reiwa" },
{ LONG, CHINA, "\u4ee4\u548c" },
{ SHORT, JAPAN, "\u4ee4\u548c" },
{ SHORT, US, "Reiwa" },
{ SHORT, CHINA, "\u4ee4\u548c" },
};
}
@Test(dataProvider="names")
public void testJapaneseNewEraName(int type, Locale locale, String expected) {
assertEquals(c.getDisplayName(ERA, type, locale), expected);
}
}

View File

@@ -1,12 +1,12 @@
#
#
# Amendments up until ISO 4217 AMENDMENT NUMBER 179
# (As of 02 May 2025)
# Amendments up until ISO 4217 AMENDMENT NUMBER 180
# (As of 22 September 2025)
#
# Version
FILEVERSION=3
DATAVERSION=179
DATAVERSION=180
# ISO 4217 currency data
AF AFN 971 2
@@ -44,7 +44,7 @@ BV NOK 578 2
BR BRL 986 2
IO USD 840 2
BN BND 96 2
BG BGN 975 2
BG BGN 975 2 2025-12-31-22-00-00 EUR 978 2
BF XOF 952 0
BI BIF 108 0
KH KHR 116 2
@@ -69,7 +69,7 @@ CR CRC 188 2
CI XOF 952 0
HR EUR 978 2
CU CUP 192 2
CW ANG 532 2 2025-04-01-04-00-00 XCG 532 2
CW XCG 532 2
CY EUR 978 2
CZ CZK 203 2
DK DKK 208 2
@@ -233,7 +233,7 @@ LK LKR 144 2
SD SDG 938 2
SR SRD 968 2
SJ NOK 578 2
SX ANG 532 2 2025-04-01-04-00-00 XCG 532 2
SX XCG 532 2
SZ SZL 748 2
SE SEK 752 2
CH CHF 756 2

View File

@@ -26,7 +26,7 @@
* @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
* 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
* 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653
* 8354343 8354344 8356096
* 8354343 8354344 8356096 8368308
* @summary Validate ISO 4217 data for Currency class.
* @modules java.base/java.util:open
* jdk.localedata
@@ -116,7 +116,7 @@ public class ValidateISO4217 {
private static final Set<String> currenciesNotYetDefined = new HashSet<>();
// Codes that are obsolete, do not have related country, extra currency
private static final String otherCodes =
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BGN-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
+ "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
+ "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
+ "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import jdk.test.lib.process.ProcessTools;
/**
* @test
* @summary Verifies cancelling window close operation does not close the window
* @requires os.family == "linux"
* @library /test/lib
* @key headful
* @run main/manual ConfirmWindowClose
*/
public class ConfirmWindowClose {
static final CompletableFuture<RuntimeException> swingError = new CompletableFuture<>();
static Process testProcess;
public static void main(String[] args) throws Exception {
if (args.length > 0) {
SwingUtilities.invokeLater(ConfirmWindowClose::showTestUI);
} else {
try {
SwingUtilities.invokeAndWait(ConfirmWindowClose::showControlUI);
swingError.get();
} finally {
if (testProcess != null) {
testProcess.destroy();
}
}
}
}
private static void showTestUI() {
JFrame frame = new JFrame("ConfirmWindowClose Test");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
JLabel l = new JLabel("<html><h1>INSTRUCTIONS</h1><p>Click on the close button on the window.</p></html>");
frame.getContentPane().add(l);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
int result = JOptionPane.showConfirmDialog(
frame,
"Do you really want to close it? (click No first)",
"Confirm Exit",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE
);
if (result == JOptionPane.YES_OPTION) {
frame.dispose();
}
}
});
frame.pack();
frame.setVisible(true);
}
private static void showControlUI() {
JFrame frame = new JFrame("ConfirmWindow Control Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel();
var layout = new GridLayout(4, 1, 10, 10);
content.setLayout(layout);
JButton runButton = new JButton("Launch Test");
runButton.addActionListener(e -> {
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(ConfirmWindowClose.class.getName(), "runTest");
try {
testProcess = pb.start();
} catch (IOException ex) {
swingError.complete(new RuntimeException(ex));
throw new RuntimeException(ex);
}
});
JButton passButton = new JButton("Pass");
passButton.addActionListener(e -> {swingError.complete(null);});
JButton failButton = new JButton("Fail");
failButton.addActionListener(e -> {swingError.completeExceptionally(new RuntimeException("The tester has pressed FAILED"));});
content.add(runButton);
content.add(failButton);
content.add(passButton);
content.add(new JLabel("<html><center><h1>INSTRUCTIONS</h1></center>" +
"<p>Press Launch Test</p>" +
"<p>In the 'ConfirmWindowClose Test' window that appears, click the window close icon on the titlebar.</p>" +
"<p>When the confirmation dialog appears click No.</p>" +
"<p>Make sure that the 'ConfirmWindowClose Test' has not disappeared.</p>" +
"<p>If the window has not disappeared, press Pass here; otherwise, press Fail.</p></html>"));
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
}

View File

@@ -10,6 +10,7 @@ java/awt/Focus/TemporaryLostComponentDeadlock.java JBR-5734 windows-all
java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java nobug macosx-all,linux-all,windows-all
java/awt/List/NofocusListDblClickTest/NofocusListDblClickTest.java nobug macosx-all,linux-all,windows-all
java/awt/List/TriggerActionEventTest.java JBR-7621 windows-all
java/awt/MenuItem/SetLabelTest.java JBR-9520 windows-x64
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-8996 windows-x64
java/awt/Modal/BlockedMouseInputTest.java JBR-8406 windows-x64
java/awt/Modal/BlockedMouseInputTest2.java JBR-8406 windows-x64
@@ -19,7 +20,7 @@ java/awt/Mouse/MouseEnterExitTest.java JBR-8096 windows-x64
java/awt/Paint/PaintNativeOnUpdate.java JBR-5397,JBR-7415 macosx-all,windows-x64
java/awt/PopupMenu/PopupMenuLocation.java JBR-5397,JBR-7375 macosx-all,windows-x64
java/awt/Robot/CheckCommonColors/CheckCommonColors.java JBR-5397,JBR-6092 macosx-all,windows-x64
java/awt/Robot/NonEmptyErrorStream.java JBR-5510,JBR-7375 linux-5.18.2-arch1-1,windows-x64
java/awt/Robot/NonEmptyErrorStream.java JBR-7375 windows-x64
java/awt/Robot/RobotWheelTest/RobotWheelTest.java JBR-5397,JBR-7377 macosx-all,windows-x64
java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java JBR-5397,JBR-7531 macosx-all,windows-x64
java/awt/ScrollPane/ScrollPaneLimitation.java JBR-8579 windows-x64
@@ -38,7 +39,7 @@ javax/accessibility/JFileChooserAccessibleDescriptionTest.java JBR-5397,JBR-7379
javax/accessibility/SlowPanelIteration/SlowPanelIteration.java JBR-870,JBR-5397 windows-x64,linux-x64,macosx-all
javax/swing/event/FocusEventCauseTest.java JBR-7381 windows-x64
javax/swing/JButton/4796987/bug4796987.java JBR-9345 windows-x64
javax/swing/JButton/8151303/PressedIconTest.java JBR-5210,JBR-5510,JBR-5397 windows-all,linux-all,macosx-all
javax/swing/JButton/8151303/PressedIconTest.java JBR-5210,JBR-5397 windows-all,macosx-all
javax/swing/JComboBox/4743225/bug4743225.java JBR-5210,JBR-5397 windows-all,macosx-all
javax/swing/JComboBox/6559152/bug6559152.java JBR-5397,JBR-7382 macosx-all,windows-x64
javax/swing/JComboBox/8041909/ActionListenerExceptionTest.java JBR-5210 windows-all
@@ -53,12 +54,13 @@ javax/swing/JInternalFrame/Test6505027.java nobug macosx-all,linux-all,w
javax/swing/JMenuBar/MenuBarRTLBug.java JBR-7385 windows-x64
javax/swing/JPopupMenu/4634626/bug4634626.java nobug macosx-all,linux-all,windows-all
javax/swing/JPopupMenu/4966112/bug4966112.java nobug macosx-all,linux-all,windows-all
javax/swing/JPopupMenu/6415145/bug6415145.java 8197552,JBR-5397 macosx-all,windows-all
javax/swing/JPopupMenu/6415145/bug6415145.java JBR-5397 macosx-all
javax/swing/JSplitPane/4615365/JSplitPaneDividerLocationTest.java JBR-5397,JBR-5505 macosx-all,windows-all
javax/swing/JTree/4518432/JTreeNodeCopyPasteTest.java JBR-5397,JBR-8939 macosx-all,windows-x64
javax/swing/text/StyledEditorKit/4506788/bug4506788.java JBR-7386 windows-x64
jb/java/awt/CustomTitleBar/DialogNativeControlsTest.java JBR-9083 windows-x64
jb/java/awt/CustomTitleBar/MaximizedWindowFocusTest.java JBR-9519 windows-x64
jb/java/awt/Desktop/AboutHandlerTest.java nobug macosx-all,linux-all,windows-all
jb/java/awt/Focus/ChainOfPopupsFocusTest.java JBR-8407 windows-x64
jb/java/awt/Focus/FrameAfterPopup.java JBR-9161 windows-x64
@@ -96,16 +98,16 @@ javax/swing/JFileChooser/4524490/bug4524490.java JBR-5397,JBR-5846 macosx-all,wi
javax/swing/JFileChooser/6520101/bug6520101.java JBR-5397,JBR-7413 macosx-all,windows-x64
javax/swing/JFileChooser/8002077/bug8002077.java JBR-4880,JBR-5397 windows-all,macosx-all
javax/swing/JLabel/4138746/JLabelMnemonicsTest.java JBR-4949,JBR-5397 linux-all,windows-all,macosx-all
javax/swing/JLabel/6596966/bug6596966.java 8197552,JBR-5397 windows-all,macosx-all
javax/swing/JLabel/6596966/bug6596966.java JBR-5397 macosx-all
javax/swing/JList/4618767/JListSelectedElementTest.java JBR-4955,JBR-5397 windows-all,macosx-all
javax/swing/JList/6462008/bug6462008.java JBR-5397,JBR-6773 macosx-all,windows-all
javax/swing/JMenu/4213634/bug4213634.java 8197552,JBR-5397 windows-all,macosx-all
javax/swing/JMenu/4515762/bug4515762.java 8197552,JBR-5397 windows-all,macosx-all
javax/swing/JMenu/4213634/bug4213634.java JBR-5397 macosx-all
javax/swing/JMenu/4515762/bug4515762.java JBR-5397 macosx-all
javax/swing/JMenu/4692443/bug4692443.java JBR-5397,JBR-6093 macosx-all,windows-all
javax/swing/JMenu/6470128/bug6470128.java 8253184,JBR-6307,JBR-5397 windows-all,linux-all,macosx-all
javax/swing/JMenuBar/4750590/bug4750590.java JBR-5397,JBR-6094 macosx-all,windows-all
javax/swing/JMenuItem/4171437/bug4171437.java JBR-5397,JBR-6112 macosx-all,windows-all
javax/swing/JMenuItem/6249972/bug6249972.java 8197552,JBR-5397 windows-all,macosx-all
javax/swing/JMenuItem/6249972/bug6249972.java JBR-5397 macosx-all
javax/swing/JMenuItem/JMenuItemSetAcceleratorTest.java JBR-5397 macosx-all
javax/swing/JPopupMenu/4458079/bug4458079.java JBR-5397 macosx-all
javax/swing/JPopupMenu/4634626/bug4634626.java 8253184,JBR-5397 windows-all,macosx-all
@@ -126,7 +128,7 @@ javax/swing/plaf/basic/BasicRootPaneUI/HiddenDefaultButtonTest.java JBR-7310 win
javax/swing/plaf/synth/7158712/bug7158712.java JBR-125,8322653,JBR-5397 linux-all,windows-all,macosx-all
javax/swing/Popup/TaskbarPositionTest.java 8310689,JBR-5397 windows-all,macosx-all
javax/swing/text/CSSBorder/6796710/bug6796710.java JBR-5397,JBR-6465 macosx-all,windows-all,linux-aarch64
sanity/client/SwingSet/src/EditorPaneDemoTest.java JBR-5397,8212240,JBR-5510,JBR-6285,8253184 macosx-all,linux-all,windows-all
sanity/client/SwingSet/src/EditorPaneDemoTest.java JBR-5397,8212240,JBR-6285,8253184 macosx-all,linux-all,windows-all
sanity/client/SwingSet/src/ToolTipDemoTest.java JBR-5397 macosx-all
sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java JBR-5397 macosx-all
sun/java2d/GdiRendering/ClipShapeRendering.java JBR-5397 macosx-all
@@ -149,7 +151,7 @@ javax/swing/JComboBox/8182031/ComboPopupTest.java 8253184,JBR-5397 windows-all,m
javax/swing/JComboBox/JComboBoxPopupMenuEventTest.java JBR-5397 macosx-all
javax/swing/JComboBox/JComboBoxScrollFocusTest.java JBR-9094 windows-x64
javax/swing/JComboBox/JComboBoxWithTitledBorderTest.java JBR-5397 macosx-all
javax/swing/JEditorPane/8195095/ImageViewTest.java 8253184,JBR-5510,JBR-6283,JBR-5397 windows-all,linux-5.18.2-arch1-1,macosx-all
javax/swing/JEditorPane/8195095/ImageViewTest.java 8253184,JBR-6283,JBR-5397 windows-all,macosx-all
javax/swing/JSpinner/4670051/DateFieldUnderCursorTest.java JBR-5397 macosx-all
# Windows (ZoomText, NVDA, or JAWS is enabled during testing)
@@ -159,8 +161,8 @@ java/awt/Choice/ChoiceFreezeTest.java JBR-6952 windows-x64
java/awt/Choice/ChoiceMouseEventOutbounds.java TBD windows-x64
java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java JBR-6857,JBR-5505 macosx-all,windows-all
java/awt/Choice/NonFocusablePopupMenuTest.java JBR-7961 windows-x64
java/awt/Choice/RemoveAllShrinkTest/RemoveAllShrinkTest.java JBR-5510,8310487,JBR-6950 linux-5.18.2-arch1-1,linux-all,windows-x64
java/awt/Choice/ResizeAutoClosesChoice/ResizeAutoClosesChoice.java JBR-5510,JBR-5905 linux-5.18.2-arch1-1,linux-all,windows-x64
java/awt/Choice/RemoveAllShrinkTest/RemoveAllShrinkTest.java 8310487,JBR-6950 linux-all,windows-x64
java/awt/Choice/ResizeAutoClosesChoice/ResizeAutoClosesChoice.java JBR-5905 linux-all,windows-x64
java/awt/Component/NativeInLightShow/NativeInLightShow.java JBR-7715 windows-x64
java/awt/Component/RepaintTest.java JBR-7754 windows-x64
java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java JBR-5538 windows-x64
@@ -184,8 +186,8 @@ java/awt/im/memoryleak/InputContextMemoryLeakTest.java JBR-5505 windows-all
java/awt/LightweightComponent/MultipleAddNotifyTest/MultipleAddNotifyTest.java JBR-9252 windows-all
java/awt/LightweightDispatcher/LWDispatcherMemoryLeakTest.java JBR-5505 windows-all
java/awt/List/ItemEventTest/ItemEventTest.java JBR-5711,JBR-5505 windows-all,linux-all
java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405,JBR-5510,JBR-5505 macosx-all,linux-5.18.2-arch1-1,windows-all
java/awt/Mixing/AWT_Mixing/JGlassPaneMoveOverlapping.java JBR-5510,JBR-5505 linux-5.18.2-arch1-1,windows-all
java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405,JBR-5505 macosx-all,windows-all
java/awt/Mixing/AWT_Mixing/JGlassPaneMoveOverlapping.java JBR-5505 windows-all
java/awt/Mixing/MixingOnDialog.java JBR-5505 windows-all
java/awt/Mixing/MixingOnShrinkingHWButton.java JBR-5505 windows-all
java/awt/Mixing/OpaqueTest.java JBR-5707,JBR-5505 linux-all,windows-all

View File

@@ -13,7 +13,6 @@ javax/swing/JComponent/7154030/bug7154030.java JBR-7713 macosx-aarch64
javax/swing/JDialog/Transparency/TransparencyTest.java JBR-7554 macosx-aarch64
javax/swing/JSplitPane/4820080/JSplitPaneDragColorTest.java JBR-7247 macosx-all
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java JBR-7404 macosx-all
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java JBR-8327 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
javax/swing/plaf/aqua/CustomComboBoxFocusTest.java JBR-5190 macosx-all
javax/swing/SwingGraphics/TranslateTest.java JBR-7510 macosx-aarch64

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