Compare commits

...

67 Commits

Author SHA1 Message Date
Nikita Provotorov
59055bc850 JBR-9719: Wayland: input methods in Speed search don't work if WLInputMethodZwpTextInputV3 logger is enabled
Resetting the text iterator of each InputMethodEvent after it gets logged.

(cherry picked from commit 3355214b43)
2025-11-28 18:50:30 +01:00
Nikita Provotorov
7666cf1882 JBR-9713: Mouse back and forth (Button4 / Button 5) no longer works on Linux in the 2025.2.5 version
JBR-9714: Horizontal scroll stopped working after 2025.2.5 update
JBR-9715: Horizontal touchpad scroll stopped working after 2025.2.5 update

Disabling the part of JDK-8351907 that disables all mouse extra buttons for XWayland GNOME of version >= 47.

(cherry picked from commit caf64eeea4)
2025-11-27 15:49:36 +01:00
Maxim Kartashev
21a1668c8f JBR-9672 Wayland: popup focus broken in Plasma 6.5.2, with Focus Stealing prevention >= Medium 2025-11-27 17:28:47 +04:00
Nikita Tsarev
aa937adccf JBR-9483 Wayland: Support toplevel icons
This patch implements support for the xdg_toplevel_icon_v1 protocol.
The image choosing logic is just to pick the largest square image for
now. The image scale factor is also not set, since it's unclear if it's
needed and how it interacts with multi-monitor setups.

NOTE: this patch introduces a dependency on wayland-protocols 1.37+.
2025-11-27 11:44:16 +01:00
Nikita Tsarev
1434025d74 JBR-9699 Build with newer wayland-protocols
Updates the CI build scripts to look for wayland protocols in
/opt/wayland-protocols
2025-11-27 11:44:06 +01:00
Vitaly Provodin
89b841701e update exclude list on results of 25.0.1_220.18 test runs 2025-11-27 12:00:28 +04:00
Vladimir Kharitonov
352117baf3 JBR-8118 metal: refactor shared textures 2025-11-26 18:08:59 +01:00
Vladimir Lagunov
79d925f6ae JBR-9531 Prevent unexpected recursive usage of java.io over nio wrappers
Shortly said, we don't need to handle recursive invocations of the `java.io` to nio adapters, while this recursion leads to problems.

# Problem

Since we're not allowed to modify public API of Java classes, an unreliable workaround `IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL` had been introduced. This trick lets us pass some object into a called function without adding a new function argument.

The trick backfired at the following code:

```java
// at java.base/java.io.IoOverNioFileSystem.initializeStreamUsingNio (simplified code)
IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.set(owner);
return initializeStreamsUsingNio0(owner, nioFs, file, nioPath, optionsForChannel, channelCleanable);

// at java.base/java.io.IoOverNioFileSystem.initializeStreamsUsingNio0
channel = nioFs.provider().newFileChannel(nioPath, optionsForChannel);
```

The intention of setting `PARENT_FOR_FILE_CHANNEL_IMPL` is to path `owner` inside a constructor of `sun.nio.ch.FileChannelImpl` which may be called by `newFileChannel(nioPath, optionsForChannel)`.

The implementation of `newFileChannel` in IntelliJ triggered class loading. The classloader of IntelliJ triggered the call `java.nio.file.Files.readAllBytes`. The latter code also invoked the constructor of `FileChannelImpl`, and the constructor got from the thread-local variable the value for the field `parent`. That value was supposed to be passed to a different invocation of the constructor.

The observable result of this bug was a `NullPointerExceptions` from `java.io.FileOutputStream.close`. Hypothetically, this bug could also lead to closing file descriptors earlier as expected in other unpredictable places.

# Rejected approaches

* The cleanest solution could be passing specific function arguments through function arguments.

  However, we may neither create a new public function in the module `java.base`, nor add an argument to an existing one. Thus, we have to keep dealing with thread-local variables.
* To hold several values in the thread-local variable.

  In this case, the constructor of `FileChannelImpl` should somehow choose the right value from the list. The only possible way for filtering values is by the provided path. It doesn't look like a performant and reliable solution.

# Chosen solution

This commit disables recursive invocations of `java.io` from `java.nio` adapters.

The chosen solution is tied to specifics of IntelliJ. The reason for introducing java.io over java.nio adapter was to be able to access files from remote machines without rewriting old code. It is not expected that an implementation of `java.nio.file.spi.FileSystemProvider` accesses the file system using `java.io`. The only imaginable way to get a `java.io` call from `java.nio` is class loading. In case of IntelliJ, it's assumed that the class loader never accesses classes and jars from a remote machine.

(cherry picked from commit 4588d8ff44)
2025-11-25 14:41:35 +00:00
Vitaly Provodin
e37c54a24f JBR-9422 revert "8296972: [macos13] java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java: getExtendedState() != 6 as expected." 2025-11-22 02:42:22 +04:00
Maxim Kartashev
d96581ebec JBR-9656 Wayland: toFront() does not work on KDE Plasma 6.5.2
KWin does not accept the serial number from a "keyboard enter" event in
a window activation request, while a recent input event serial is OK.
Gnome, however, requires the "keyboard enter" event serial.
2025-11-21 12:20:04 +04:00
Vitaly Provodin
f37e00d801 update exclude list on results of 25.0.1_212.14 test runs 2025-11-21 07:40:22 +04:00
Maxim Kartashev
a49aa72e7b JBR-6187 Wayland: implement server-side decoration support
Use -Dsun.awt.wl.WindowDecorationStyle=server to activate
2025-11-20 14:07:41 +04:00
Nikita Tsarev
5af08d88d5 JBR-9642 Wayland: Call wl_data_offer.finish()
This patch adds a call to wl_data_offer.finish() upon a successful
completion of a drag-and-drop operation, as well as more synchronized
annotations in WLDataOffer, to match the existing ones.

Calling finish() doesn't seem to be required by most compositors when
performing drag-and-drop, at least within the same window. Other
toolkits, such as Qt, only call it when dealing with cross-application
drag-and-drop. In the interest of maximal compatibility, this patch
implements calling finish() always when a drag-and-drop operation
succeeds.
2025-11-18 10:14:59 +01:00
Nikita Gubarkov
87a46979f3 JBR-9640 Add CHECK_EXCEPTION to CGraphicsDevice.nativeGetDisplayConfiguration 2025-11-17 16:12:53 +01:00
Nikita Tsarev
e7a86af739 JBR-9581 Wayland: Find xkbcommon at configure time
This commit changes how WLToolkit loads libxkbcommon. It will now be
linked as a normal dynamic library at build time, instead of being
loaded via dlopen. This commit also introduces dependency on
libxkbcommon headers and removes the corresponding declarations from
WLKeyboard.c.
2025-11-17 10:38:52 +01:00
Nikita Provotorov
60bfa2b12e JBR-9616: JBR can't be built on Windows: "LAUNCHER_ARGS must be defined".
fixup! JRE-681 [windows] direct drawing into frame graphics may have wrong translate

Using LIBAWT_EXTRA_HEADER_DIRS instead of LIBAWT_EXTRA_SRC to get src/java.base/windows/native/launcher/java_rc.h discoverable by src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp.
2025-11-14 16:51:18 +01:00
Nikita Tsarev
ae6360371c JBR-9591 Wayland: Fix wrong DnD action on KWin
This patch implements a workaround for a bug that exists on KWin 6.5. For
some reason, KWin sends a wl_data_source.action(0) event immediately
after wl_data_source.dnd_drop_finished(). This makes the drag source
think that the DnD operation failed, even though it succeeded.
The workaround it to ignore the wl_data_source.action() events
after a successful wl_data_source.dnd_drop_finished()

In addition to this, this patch also fixes some inconsistency with
translating between AWT and Wayland DnD operation masks. This doesn't
have any visible effect though, since the mask values happen to be the
same.
2025-11-14 16:20:38 +01:00
Maxim Kartashev
f8aee55ea6 JBR-9598 Wayland: auto-detect Wayland session at startup
Adds -Dawt.toolkit.name=auto to prefer WLToolkit over XToolkit when
available. The default is still XToolkit.
2025-11-14 14:04:53 +04:00
Maxim Kartashev
ffc581146c JBR-9608 Correct README.md to suggest contributing through OpenJDK 2025-11-13 15:04:36 +04:00
Maxim Kartashev
75930f77d2 JBR-9577 Extra info on JVM crash to the terminal 2025-11-13 12:35:35 +04:00
Nikita Gubarkov
7b721d2610 JBR-9505 Vulkan: Remove sun.java2d.vulkan.accelsd from tests
(cherry picked from commit 3fb012e9dd)
2025-11-12 17:41:22 +01:00
Vitaly Provodin
fed9ce336e update exclude list on results of 25.0.1_197.11 test runs 2025-11-12 12:50:25 +04:00
Dmitry Drobotov
14be13239e JBR-9580 Fix crash in [MenuAccessibility accessibilityChildren]
* Add null checks for variables that can have null values to prevent hard crash
* Add missing CHECK_EXCEPTION after JNI call
* Add missing DeleteLocalRef for axComponent

(cherry picked from commit 96fcd9e591)
2025-11-11 20:28:55 +01:00
Vladimir Dvorak
c9aea14597 JBR-9548 DCEVM: Ensure updated class versions in dictionary in doit() 2025-11-11 20:03:40 +01:00
Maxim Kartashev
d619feefc6 JBR-5989 Wayland: added more tests to jdk_awt_wayland 2025-11-11 18:06:00 +04:00
bourgesl
b38204cb12 JBR-9609 JBR Metal compilation error on Intel MacBooks
Wrapped MTLDrawable.drawableID usages in getDrawableId to check macOS version
2025-11-11 11:23:07 +01:00
Sergey Shelomentsev
c7fe20689c JBR-9610 Set TimerQueue thread exclusion for BugJBR9563.java 2025-11-11 11:38:31 +02:00
Vitaly Provodin
bb52503876 update exclude list on results of 25.0.1_190.10 test runs 2025-11-06 16:44:43 +04:00
Nikita Gubarkov
a9554a0e4a JBR-5594 Pass display configuration from outside on full display update 2025-11-06 13:31:38 +01:00
Nikita Gubarkov
cbae1a769b JBR-5594 Pass display configuration info from AppKit to EDT 2025-11-06 13:31:37 +01:00
bourgesl
505522f2e2 JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke
Minimal changes for JBR-21: added @try/&@catch(nsexception) in ThreadUtilities.processQueuedCallbacks() to handle any native or java exception and avoid crashing the main run loop
2025-11-05 22:47:04 +01:00
bourgesl
9e729bf99d Revert "JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke"
This reverts commit 39743018bb.
2025-11-05 22:46:44 +01:00
bourgesl
14eaa570d1 Revert "JBR-8651 remove logging producing warnings in stderr"
This reverts commit e880107619.
2025-11-05 22:46:43 +01:00
Nikita Tsarev
54b65e514f JBR-9542 Wayland: Fix modifier mask on modifier key press/release
When pressing a modifier key such as Shift or Alt, other toolkits
include the corresponding bit in the modifier mask. Similiarly, when
releasing a modifier key, other toolkits will not include this bit if
the just released modifier key was the last key producing this bit.

When pressing such a key, Wayland compositors first send the
wl_keyboard.key event, and only then the wl_keyboard.modifiers event.
This causes the reported AWT modifier mask to be inconsistent with
XToolkit. This patch fixes this.
2025-11-05 17:15:19 +01:00
Vladimir Dvorak
86e6947981 JBR-9578 DCEVM: update class only in dictionary 2025-11-05 13:01:59 +01:00
Sergey Shelomentsev
0f7c371233 JBR-9563 Add test to verify that new threads aren't spawned infinitely 2025-11-05 13:15:50 +02:00
Vitaly Provodin
e880107619 JBR-8651 remove logging producing warnings in stderr 2025-11-01 16:11:48 +01:00
bourgesl
39743018bb JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke
Rewritten exception handling to adopt the improved NSApplicationAWT exception handler (log all exceptions, avoid crash GUI)
Fixed JNI_COCOA_EXIT(env) usages to test also pending JNI exceptions
Added JNI_COCOA_EXIT_FATAL(message) used by NSApplicationAWT.sendEvent to report a crash with full details
Unified logException to report both crash and exceptions
Added isAWTCrashOnException() using the system property 'apple.awt.crashOnException' to crash on any exception occuring in NSApplication level
Added missing CHECK_EXCEPTION after (*env)->Call...Method()
Intercept all exception in NSApplicationAWT as NSExceptionHandlerDelegate + added tests in LWCToolkit (native) and Java code to test all exceptions are reported in logs and caught properly

(cherry picked from commit 8664158b6de5e71374212a4a7807a038d925c9a1)
2025-10-31 17:03:19 +01:00
Vitaly Provodin
ceb2dcb091 update exclude list on results of 25.0.1_186.7 test runs 2025-10-30 15:56:05 +04:00
Nikita Tsarev
fe29694915 JBR-9547: Fix macOS build failure with Xcode 26.0.1 2025-10-28 12:50:20 +01: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
174 changed files with 2963 additions and 2248 deletions

3
.github/README.md vendored
View File

@@ -254,8 +254,7 @@ configurations (for example, `release` and `fastdebug`), supply the `--conf <con
Then open the git root directory as a project in IDEA.
## Contributing
We are happy to receive your pull requests!
Before you submit one, please sign our [Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/).
Please contribute your changes through [OpenJDK](https://dev.java/contribute/openjdk/).
## Resources
* [JetBrains Runtime on GitHub](https://github.com/JetBrains/JetBrainsRuntime).

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

@@ -27,6 +27,12 @@ JCEF_PATH=${JCEF_PATH:=./jcef_linux_aarch64}
function do_configure {
GTK_SHELL_PATH=/gtk-shell.xml
WAYLAND_PROTOCOLS_PATH=/opt/wayland-protocols
WITH_WAYLAND_PROTOCOLS=
if [ -e "$WAYLAND_PROTOCOLS_PATH" ]; then
WITH_WAYLAND_PROTOCOLS="--with-wayland-protocols=$WAYLAND_PROTOCOLS_PATH"
fi
if [ ! -e $GTK_SHELL_PATH ]; then
echo $GTK_SHELL_PATH" does not exist"
@@ -54,6 +60,7 @@ function do_configure {
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
$WITH_BUNDLED_FREETYPE \
$WITH_WAYLAND_PROTOCOLS \
|| do_exit $?
}

View File

@@ -34,6 +34,12 @@ function do_configure {
fi
GTK_SHELL_PATH=/gtk-shell.xml
WAYLAND_PROTOCOLS_PATH=/opt/wayland-protocols
WITH_WAYLAND_PROTOCOLS=
if [ -e "$WAYLAND_PROTOCOLS_PATH" ]; then
WITH_WAYLAND_PROTOCOLS="--with-wayland-protocols=$WAYLAND_PROTOCOLS_PATH"
fi
if [ ! -e $GTK_SHELL_PATH ]; then
echo $GTK_SHELL_PATH" does not exist"
@@ -68,6 +74,7 @@ function do_configure {
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
$WITH_BUNDLED_FREETYPE \
$WITH_WAYLAND_PROTOCOLS \
|| do_exit $?
}

View File

@@ -40,12 +40,23 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
[specify the root directory for the wayland protocols xml files])])
AC_ARG_WITH(gtk-shell1-protocol, [AS_HELP_STRING([--with-gtk-shell1-protocol],
[specify the path to the gtk-shell1 Wayland protocol xml file])])
AC_ARG_WITH(xkbcommon, [AS_HELP_STRING([--with-xkbcommon],
[specify prefix directory for the xkbcommon package
(expecting the headers under PATH/include)])])
AC_ARG_WITH(xkbcommon-include, [AS_HELP_STRING([--with-xkbcommon-include],
[specify directory for the xkbcommon include files])])
AC_ARG_WITH(xkbcommon-lib, [AS_HELP_STRING([--with-xkbcommon-lib],
[specify directory for the xkbcommon library files])])
if test "x$NEEDS_LIB_WAYLAND" = xfalse; then
if (test "x${with_wayland}" != x && test "x${with_wayland}" != xno) || \
(test "x${with_wayland_include}" != x && test "x${with_wayland_include}" != xno); then
AC_MSG_WARN([[wayland not used, so --with-wayland[-*] is ignored]])
fi
if (test "x${with_xkbcommon}" != x && test "x${with_xkbcommon}" != xno) || \
(test "x${with_xkbcommon_include}" != x && test "x${with_xkbcommon_include}" != xno); then
AC_MSG_WARN([[wayland not used, so --with-xkbcommon[-*] is ignored]])
fi
WAYLAND_CFLAGS=
WAYLAND_LIBS=
else
@@ -55,6 +66,9 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
if test "x${with_wayland}" = xno || test "x${with_wayland_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of wayland. Remove the --without-wayland option.])
fi
if test "x${with_xkbcommon}" = xno || test "x${with_xkbcommon_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of xkbcommon. Remove the --without-xkbcommon option.])
fi
if test "x${with_wayland}" != x; then
AC_MSG_CHECKING([for wayland headers])
@@ -121,7 +135,52 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
HELP_MSG_MISSING_DEPENDENCY([wayland])
AC_MSG_ERROR([Could not find wayland! $HELP_MSG ])
fi
WAYLAND_CFLAGS="${WAYLAND_INCLUDES} ${WAYLAND_DEFINES}"
XKBCOMMON_FOUND=no
XKBCOMMON_INCLUDES=
XKBCOMMON_LIBS=-lxkbcommon
if test "x${with_xkbcommon}" != x; then
AC_MSG_CHECKING([for xkbcommon headers])
if test -s "${with_xkbcommon}/include/xkbcommon/xkbcommon.h" &&
test -s "${with_xkbcommon}/include/xkbcommon/xkbcommon-compose.h"; then
XKBCOMMON_INCLUDES="-I${with_xkbcommon}/include"
XKBCOMMON_LIBS="-L${with_xkbcommon}/lib ${XKBCOMMON_LIBS}"
XKBCOMMON_FOUND=yes
AC_MSG_RESULT([$XKBCOMMON_FOUND])
else
AC_MSG_ERROR([Can't find 'include/xkbcommon/xkbcommon.h' and 'include/xkbcommon/xkbcommon-compose.h' under ${with_xkbcommon} given with the --with-xkbcommon option.])
fi
fi
if test "x${with_xkbcommon_include}" != x; then
AC_MSG_CHECKING([for xkbcommon headers])
if test -s "${with_xkbcommon_include}/xkbcommon/xkbcommon.h" &&
test -s "${with_xkbcommon_include}/xkbcommon/xkbcommon-compose.h"; then
XKBCOMMON_INCLUDES="-I${with_xkbcommon_include}"
XKBCOMMON_FOUND=yes
AC_MSG_RESULT([$XKBCOMMON_FOUND])
else
AC_MSG_ERROR([Can't find 'include/xkbcommon/xkbcommon.h' and 'include/xkbcommon/xkbcommon-compose.h' under ${with_xkbcommon_include} given with the --with-xkbcommon-include option.])
fi
fi
if test "x${with_xkbcommon_lib}" != x; then
XKBCOMMON_LIBS="-L${with_xkbcommon_lib} ${XKBCOMMON_LIBS}"
fi
if test "x${XKBCOMMON_FOUND}" != xyes; then
AC_CHECK_HEADERS([xkbcommon/xkbcommon.h xkbcommon/xkbcommon-compose.h],
[ XKBCOMMON_FOUND=yes ],
[ XKBCOMMON_FOUND=no; break ]
)
fi
if test "x$XKBCOMMON_FOUND" != xyes; then
HELP_MSG_MISSING_DEPENDENCY([xkbcommon])
AC_MSG_ERROR([Could not find xkbcommon! $HELP_MSG ])
fi
WAYLAND_LIBS="${WAYLAND_LIBS} ${XKBCOMMON_LIBS}"
WAYLAND_CFLAGS="${WAYLAND_INCLUDES} ${XKBCOMMON_INCLUDES} ${WAYLAND_DEFINES}"
fi
AC_SUBST(WAYLAND_CFLAGS)
AC_SUBST(WAYLAND_LIBS)

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

@@ -65,6 +65,7 @@ ifeq ($(call isTargetOs, aix), false)
CXXFLAGS := $(LIBJSOUND_CFLAGS), \
DISABLED_WARNINGS_gcc := undef unused-variable, \
DISABLED_WARNINGS_clang := undef unused-variable, \
DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_Ports.cpp := vla-cxx-extension, \
DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_MidiUtils.c := \
unused-but-set-variable, \
DISABLED_WARNINGS_clang_DirectAudioDevice.c := unused-function, \

View File

@@ -33,10 +33,12 @@ WAYLAND_BASIC_PROTOCOL_FILES := \
$(WAYLAND_PROTOCOLS_ROOT)/stable/viewporter/viewporter.xml \
$(WAYLAND_PROTOCOLS_ROOT)/stable/xdg-shell/xdg-shell.xml \
$(WAYLAND_PROTOCOLS_ROOT)/staging/xdg-activation/xdg-activation-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml \
$(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 \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml \
$(GTK_SHELL1_PROTOCOL_PATH) \
#

View File

@@ -58,7 +58,6 @@ ifeq ($(call isTargetOs, windows), true)
$(TOPDIR)/src/$(MODULE)/share/native/common/font \
$(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \
$(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \
$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/launcher \
#
endif
@@ -102,6 +101,7 @@ ifeq ($(call isTargetOs, windows), true)
LIBAWT_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons
LIBAWT_VERSIONINFO_RESOURCE := \
$(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc
LIBAWT_EXTRA_HEADER_DIRS += $(TOPDIR)/src/java.base/windows/native/launcher
endif
# This is the object file to provide the dladdr API, which is not

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

@@ -352,16 +352,6 @@ void ClassLoaderDataGraph::verify_dictionary() {
}
}
// (DCEVM) - iterate over dict classes
void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
cld->dictionary()->classes_do(klass_closure);
}
}
}
// (DCEVM) rollback redefined classes
void ClassLoaderDataGraph::rollback_redefinition() {
ClassLoaderDataGraphIterator iter;
@@ -373,17 +363,27 @@ void ClassLoaderDataGraph::rollback_redefinition() {
}
// (DCEVM) - iterate over all classes in all dictionaries
bool ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass) {
bool ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old) {
bool ok = false;
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
ok = cld->dictionary()->update_klass(current, name, k, old_klass) || ok;
ok = cld->dictionary()->update_klass(current, name, k, old_klass, check_old) || ok;
}
}
return ok;
}
// (DCEVM) - iterate over all classes in all dictionaries
void ClassLoaderDataGraph::dictionary_classes_do_classes_do_safepoint(void f(InstanceKlass* const)) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
cld->dictionary()->classes_do_safepoint(f);
}
}
}
void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData *cld = iter.get_next()) {

View File

@@ -102,9 +102,9 @@ class ClassLoaderDataGraph : public AllStatic {
static void walk_metadata_and_clean_metaspaces();
// (DCEVM) Enhanced class redefinition
static void dictionary_classes_do(KlassClosure* klass_closure);
static void rollback_redefinition();
static bool dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass);
static bool dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old);
static void dictionary_classes_do_classes_do_safepoint(void f(InstanceKlass* const));
static void verify_dictionary();
static void print_dictionary(outputStream* st);

View File

@@ -211,15 +211,23 @@ class UpdateKlassDcevm : public StackObj {
InstanceKlass* _new_klass;
InstanceKlass* _old_klass;
bool _replaced;
bool _check_old;
public:
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass) :
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass, bool check_old) :
_new_klass(new_klass),
_old_klass(old_klass),
_replaced(false) {
_replaced(false),
_check_old(check_old) {
}
void operator()(InstanceKlass** old_table_value) {
assert(*old_table_value == _old_klass, "should be old class");
InstanceKlass* table_class = *old_table_value;
assert(!_check_old || table_class == _old_klass, "should be old class");
assert(table_class->class_loader_data() == _new_klass->class_loader_data(), "Must be same class loader");
if (!_check_old && table_class->new_version() != nullptr) {
ResourceMark rm;
log_debug(redefine, class, redefine, metadata)("Updating old class from doit() %s", table_class->name()->as_C_string());
}
*old_table_value = _new_klass;
_replaced = true;
}
@@ -230,14 +238,14 @@ public:
};
// (DCEVM) replace old_class by new class in dictionary
bool Dictionary::update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass) {
UpdateKlassDcevm found(k, old_klass);
bool Dictionary::update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old) {
UpdateKlassDcevm found(k, old_klass, check_old);
DictionaryLookup lookup(class_name);
InstanceKlass* result = nullptr;
bool needs_rehashing = false;
bool ret = _table->insert_get(current, lookup, old_klass, found);
return ret || found.get_replaced();
// (DCEVM): old_klass is replaced with the new one in UpdateKlassDcevm::operator(),
// which is invoked when class_name is found in the dictionary.
bool exists = _table->get(current, lookup, found);
return exists && found.get_replaced();
}
class RollBackDcevm : public StackObj {

View File

@@ -77,7 +77,7 @@ public:
void verify();
// (DCEVM) Enhanced class redefinition
bool update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass);
bool update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old);
void rollback_redefinition();
private:

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.
@@ -1386,10 +1386,9 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* ol
if (is_redefining) {
// Update all dictionaries containing old_class to new_class
// outcome must be same as result of standard redefinition, that does not create a new Klass
ClassLoaderDataGraph_lock->lock();
MutexLocker lock(ClassLoaderDataGraph_lock);
Symbol* name_h = k->name();
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass);
ClassLoaderDataGraph_lock->unlock();
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass, true);
assert (ok, "must have found old class and updated!");
}
check_constraints(k, loader_data, !is_redefining, CHECK);
@@ -1487,7 +1486,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 +1526,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

@@ -432,6 +432,9 @@ protected:
const Klass* newest_version() const { return _new_version == nullptr ? this : _new_version->newest_version(); }
Klass* newest_version() { return _new_version == nullptr ? this : _new_version->newest_version(); }
const Klass* oldest_version() const { return _old_version == nullptr ? this : _old_version->oldest_version(); }
Klass* oldest_version() { return _old_version == nullptr ? this : _old_version->oldest_version(); }
const Klass* active_version() const { return _new_version == nullptr || _new_version->is_redefining() ? this : _new_version->active_version(); }
Klass* active_version() { return _new_version == nullptr || _new_version->is_redefining() ? this : _new_version->active_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,9 +218,7 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, int offset) {
DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
if (AllowEnhancedClassRedefinition) {
while (field_klass->old_version() != NULL) {
field_klass = field_klass->old_version();
}
field_klass = field_klass->oldest_version();
}
uintptr_t klass_hash = field_klass->identity_hash();
return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
@@ -242,9 +240,9 @@ 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) {
k = k->old_version();
}
// DCEVM: use the oldest class version so all pre-existing IDs
// from old classes match IDs of the new (current) class.
k = k->oldest_version();
}
do {
@@ -253,6 +251,11 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
if ((k->identity_hash() & klass_mask) == klass_hash)
return true;
k = k->super();
if (AllowEnhancedClassRedefinition) {
// DCEVM: Same for each superclass: normalize to the oldest version
// so old IDs match the new class IDs.
k = k->oldest_version();
}
} while (k != nullptr);
return false;
}

View File

@@ -62,7 +62,6 @@
#include "utilities/bitMap.inline.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "utilities/events.hpp"
#include "oops/constantPool.inline.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
#endif
@@ -695,6 +694,16 @@ void VM_EnhancedRedefineClasses::doit() {
new_class->old_version()->set_new_version(new_class);
}
// Update Dictionaries to ensure all references contain the new class versions.
// During load_new_class_versions(), another thread may have loaded an old version, so this pass replaces
// any remaining old ones.
for (int i = 0; i < _new_classes->length(); i++) {
InstanceKlass* new_class = _new_classes->at(i);
InstanceKlass* old_class = InstanceKlass::cast(new_class->old_version());
Symbol *name_h = new_class->name();
ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread::current(), name_h, new_class, old_class, false);
}
for (int i = 0; i < _new_classes->length(); i++) {
Klass* new_class = _new_classes->at(i);
redefine_single_class(current, _new_classes->at(i));
@@ -917,7 +926,7 @@ void VM_EnhancedRedefineClasses::doit() {
}
}
log_trace(redefine, class, redefine, metadata)("calling check_class");
ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do_safepoint(check_class);
ClassLoaderDataGraph::dictionary_classes_do_classes_do_safepoint(check_class);
#ifdef PRODUCT
}
#endif

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

@@ -1312,24 +1312,24 @@ void VMError::report(outputStream* st, bool _verbose) {
NativeHeapTrimmer::print_state(st);
st->cr();
STEP("JNI global references")
st->print_cr("JNI global refs:");
JNIHandles::print_on_unsafe(st);
JNIHandles::print_memory_usage_on(st);
STEP_IF("JNI global references", _verbose)
st->print_cr("JNI global refs:");
JNIHandles::print_on_unsafe(st);
JNIHandles::print_memory_usage_on(st);
STEP_IF("Process memory usage", _verbose)
print_process_memory_usage(st);
STEP("OOME stack traces")
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
STEP_IF("OOME stack traces", _verbose)
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
STEP("Classloader stats")
st->print_cr("Classloader memory used:");
FREE_C_HEAP_ARRAY(void*, _ballast_memory);
_ballast_memory = nullptr;
print_classloaders_stats(st);
print_dup_classes(st); // do it separately in case we're low on memory
STEP_IF("Classloader stats", _verbose)
st->print_cr("Classloader memory used:");
FREE_C_HEAP_ARRAY(void*, _ballast_memory);
_ballast_memory = nullptr;
print_classloaders_stats(st);
print_dup_classes(st); // do it separately in case we're low on memory
STEP_IF("printing system", _verbose)
st->print_cr("--------------- S Y S T E M ---------------");

View File

@@ -159,5 +159,84 @@ public class IoOverNio {
* <p>
* The problem was found with the test {@code jtreg:test/jdk/java/io/FileDescriptor/Sharing.java}.
*/
public static final ThreadLocal<Closeable> PARENT_FOR_FILE_CHANNEL_IMPL = new ThreadLocal<>();
public static class ParentForFileChannelImplHolder {
private static final ThreadLocal<Closeable> holder = new ThreadLocal<>();
private ParentForFileChannelImplHolder() {}
public static Closeable get() {
return holder.get();
}
public static void set(Closeable parent) {
RecursionGuard.ensureActive();
holder.set(parent);
}
public static void remove() {
RecursionGuard.ensureActive();
holder.remove();
}
}
/**
* <p>With java.io over java.nio backend, it's possible that some code invokes file system operations while
* already executing a similar operation. An example is when a classloader uses {@link FileSystems#getDefault()}
* during class loading. Such cases break usage of {@link ParentForFileChannelImplHolder}.</p>
*
* <p>This class is to be used around places that can hypothetically access {@link ParentForFileChannelImplHolder}
* recursively.</p>
*/
public static class RecursionGuard implements Closeable {
private static final ThreadLocal<RecursionGuard> HEAD = new ThreadLocal<>();
private final RecursionGuard parent;
private final Object label;
private final ThreadLocalCloseable additionalClosable;
/**
* @param label A unique object for a specific method. The object is used for reference equality.
* A static string or a reference to a class is a good candidate.
*/
public static RecursionGuard create(Object label) {
ThreadLocalCloseable additionalClosable = null;
for (var guard = HEAD.get(); guard != null; guard = guard.parent) {
if (guard.label == label) {
additionalClosable = disableInThisThread();
break;
}
}
var result = new RecursionGuard(HEAD.get(), label, additionalClosable);
HEAD.set(result);
return result;
}
private RecursionGuard(RecursionGuard parent, Object label, ThreadLocalCloseable additionalClosable) {
this.parent = parent;
this.label = label;
this.additionalClosable = additionalClosable;
}
public static void ensureActive() {
if (HEAD.get() == null) {
throw new Error("RecursionGuard is not installed");
}
}
@Override
public void close() {
HEAD.set(parent);
if (additionalClosable != null) {
additionalClosable.close();
}
}
}
/**
* Intended only for suppressing warnings about unused variables.
*/
@SuppressWarnings("unused")
public static void blackhole(Object any) {
// Nothing here.
}
}

View File

@@ -156,37 +156,40 @@ public class FileInputStream extends InputStream
}
path = file.getPath();
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null && path != null) {
try {
nioPath = nioFs.getPath(path);
isRegularFile = Files.isRegularFile(nioPath);
} catch (InvalidPathException _) {
// Nothing.
try (var guard = IoOverNio.RecursionGuard.create(FileInputStream.class)) {
IoOverNio.blackhole(guard);
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null && path != null) {
try {
nioPath = nioFs.getPath(path);
isRegularFile = Files.isRegularFile(nioPath);
} catch (InvalidPathException _) {
// Nothing.
}
}
}
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
useNio = nioPath != null && isRegularFile == Boolean.TRUE;
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
useNio = nioPath != null && isRegularFile == Boolean.TRUE;
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, Set.of(StandardOpenOption.READ), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(path);
FileCleanable.register(fd); // open set the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileInputStream for %s%n", file);
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, Set.of(StandardOpenOption.READ), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(path);
FileCleanable.register(fd); // open set the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileInputStream for %s%n", file);
}
}
}

View File

@@ -225,46 +225,49 @@ public class FileOutputStream extends OutputStream
}
this.path = file.getPath();
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
useNio = path != null && nioFs != null;
if (useNio) {
Path nioPath = nioFs.getPath(path);
try (var guard = IoOverNio.RecursionGuard.create(FileOutputStream.class)) {
IoOverNio.blackhole(guard);
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
useNio = path != null && nioFs != null;
if (useNio) {
Path nioPath = nioFs.getPath(path);
// java.io backend doesn't open DOS hidden files for writing, but java.nio.file opens.
// This code mimics the old behavior.
if (nioFs.getSeparator().equals("\\")) {
DosFileAttributes attrs = null;
try {
var view = Files.getFileAttributeView(nioPath, DosFileAttributeView.class);
if (view != null) {
attrs = view.readAttributes();
// java.io backend doesn't open DOS hidden files for writing, but java.nio.file opens.
// This code mimics the old behavior.
if (nioFs.getSeparator().equals("\\")) {
DosFileAttributes attrs = null;
try {
var view = Files.getFileAttributeView(nioPath, DosFileAttributeView.class);
if (view != null) {
attrs = view.readAttributes();
}
} catch (IOException | UnsupportedOperationException _) {
// Windows paths without DOS attributes? Not a problem in this case.
}
if (attrs != null && (attrs.isHidden() || attrs.isDirectory())) {
throw new FileNotFoundException(file.getPath() + " (Access is denied)");
}
} catch (IOException | UnsupportedOperationException _) {
// Windows paths without DOS attributes? Not a problem in this case.
}
if (attrs != null && (attrs.isHidden() || attrs.isDirectory())) {
throw new FileNotFoundException(file.getPath() + " (Access is denied)");
}
Set<OpenOption> options = append
? Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
: Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, options, channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
this.fd = new FileDescriptor();
fd.attach(this);
open(this.path, append);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileOutputStream for %s%n", file);
}
Set<OpenOption> options = append
? Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
: Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, options, channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
this.fd = new FileDescriptor();
fd.attach(this);
open(this.path, append);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileOutputStream for %s%n", file);
}
}

View File

@@ -273,10 +273,10 @@ class IoOverNioFileSystem extends FileSystem {
try {
// This tricky thread local variable allows specifying an argument for sun.nio.ch.FileChannelImpl.<init>
// which is not present in the NIO public API and which is not easy to specify another way.
IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.set(owner);
IoOverNio.ParentForFileChannelImplHolder.set(owner);
return initializeStreamsUsingNio0(owner, nioFs, file, nioPath, optionsForChannel, channelCleanable);
} finally {
IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.remove();
IoOverNio.ParentForFileChannelImplHolder.remove();
}
}
@@ -876,7 +876,8 @@ class IoOverNioFileSystem extends FileSystem {
@Override
public boolean delete(File f) {
try {
try (var guard = IoOverNio.RecursionGuard.create("IoOverNioFileSystem.delete")) {
IoOverNio.blackhole(guard);
boolean result = delete0(f, true);
if (DEBUG.writeTraces()) {
System.err.printf("IoOverNioFileSystem.delete(%s) = %b%n", f, result);

View File

@@ -279,47 +279,50 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
path = name;
FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null) {
try {
nioPath = nioFs.getPath(path);
} catch (InvalidPathException _) {
// Nothing.
try (var guard = IoOverNio.RecursionGuard.create(RandomAccessFile.class)) {
IoOverNio.blackhole(guard);
FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null) {
try {
nioPath = nioFs.getPath(path);
} catch (InvalidPathException _) {
// Nothing.
}
}
}
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
boolean isRegularFile;
try {
isRegularFile = nioPath != null &&
Files.readAttributes(nioPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS).isRegularFile();
}
catch (NoSuchFileException _) {
isRegularFile = true;
}
catch (IOException _) {
isRegularFile = false;
}
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
boolean isRegularFile;
try {
isRegularFile = nioPath != null &&
Files.readAttributes(nioPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS).isRegularFile();
}
catch (NoSuchFileException _) {
isRegularFile = true;
}
catch (IOException _) {
isRegularFile = false;
}
useNio = nioPath != null && isRegularFile;
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, optionsForChannel(imode), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(name, imode);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a RandomAccessFile for %s%n", file);
useNio = nioPath != null && isRegularFile;
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, optionsForChannel(imode), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(name, imode);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a RandomAccessFile for %s%n", file);
}
}
}

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

@@ -140,7 +140,7 @@ public class FileChannelImpl
this.sync = sync;
this.direct = direct;
if (parent == null) {
parent = IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.get();
parent = IoOverNio.ParentForFileChannelImplHolder.get();
}
this.parent = parent;
if (direct) {

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

@@ -144,9 +144,6 @@ typedef enum awt_toolkit {
TK_WAYLAND = 2
} awt_toolkit;
// TODO when wayland support will be fully implemented change to TK_UNKNOWN
// currently wayland support is not Production-Ready ready so default awt toolkit is X11
// wayland could be chosen manually via passing -Dawt.toolkit.name=WLToolkit argument
static awt_toolkit _awt_toolkit = TK_X11;
/*
@@ -759,33 +756,48 @@ CallJavaMainInNewThread(jlong stack_size, void* args) {
/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
#define MAX_PID_STR_SZ 20
#ifdef __linux
static char*
getToolkitNameByEnv() {
if (_awt_toolkit == TK_UNKNOWN) {
char *xdg_session_type = getenv("XDG_SESSION_TYPE");
if (xdg_session_type != NULL && strcmp(xdg_session_type, "wayland") == 0) {
_awt_toolkit = TK_WAYLAND;
} else if (xdg_session_type != NULL && strcmp(xdg_session_type, "x11") == 0) {
_awt_toolkit = TK_X11;
} else if (getenv("DISPLAY") != NULL) {
_awt_toolkit = TK_X11;
} else if (getenv("WAYLAND_DISPLAY") != NULL) {
_awt_toolkit = TK_WAYLAND;
GetToolkitName(void) {
if (_awt_toolkit == TK_UNKNOWN) { // Prefer WLToolkit, then XToolkit
void* libwayland = dlopen(VERSIONED_JNI_LIB_NAME("wayland-client", "0"), RTLD_LAZY | RTLD_LOCAL);
if (!libwayland) {
// Fallback to any development version available on the system
libwayland = dlopen(JNI_LIB_NAME("wayland-client"), RTLD_LAZY | RTLD_LOCAL);
}
if (libwayland) {
typedef void* (*wl_display_connect_t)(const char*);
typedef void (*wl_display_disconnect_t)(void*);
wl_display_connect_t fp_wl_display_connect = dlsym(libwayland, "wl_display_connect");
wl_display_disconnect_t fp_wl_display_disconnect = dlsym(libwayland, "wl_display_disconnect");
if (fp_wl_display_connect && fp_wl_display_disconnect) {
void* display = fp_wl_display_connect(NULL);
if (display) {
_awt_toolkit = TK_WAYLAND;
fp_wl_display_disconnect(display);
}
}
dlclose(libwayland);
}
}
return _awt_toolkit == TK_WAYLAND ? "WLToolkit" : "XToolkit";
}
#endif // __linux
int
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char **argv,
int mode, char *what, int ret)
{
char *toolkit_name = getToolkitNameByEnv();
#ifdef __linux
char *toolkit_name = GetToolkitName();
size_t toolkit_name_size = JLI_StrLen("-Dawt.toolkit.name=") + JLI_StrLen(toolkit_name) + 1;
char *toolkit_option = (char *)JLI_MemAlloc(toolkit_name_size);
snprintf(toolkit_option, toolkit_name_size, "-Dawt.toolkit.name=%s", toolkit_name);
AddOption(toolkit_option, NULL);
#endif // __linux
ShowSplashScreen();
return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
@@ -806,7 +818,10 @@ RegisterThread()
jboolean
ProcessPlatformOption(const char *arg)
{
if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=WLToolkit") == 0) {
if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=auto") == 0) {
_awt_toolkit = TK_UNKNOWN;
return JNI_TRUE;
} else if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=WLToolkit") == 0) {
_awt_toolkit = TK_WAYLAND;
return JNI_TRUE;
} else if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=XToolkit") == 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

@@ -27,6 +27,7 @@ package com.apple.eawt;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.desktop.AboutEvent;
import java.awt.desktop.AboutHandler;
@@ -65,8 +66,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import sun.awt.AppContext;
import sun.awt.CGraphicsDevice;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.util.logging.PlatformLogger;
class _AppEventHandler {
@@ -274,9 +275,14 @@ class _AppEventHandler {
logger.fine("NOTIFY_SCREEN_CHANGE_PARAMETERS");
}
if (AppContext.getAppContext() != null) {
EventQueue.invokeLater(
() -> ((SunGraphicsEnvironment) GraphicsEnvironment.
getLocalGraphicsEnvironment()).displayParametersChanged());
CGraphicsDevice.DisplayConfiguration displayConfiguration = CGraphicsDevice.DisplayConfiguration.get();
EventQueue.invokeLater(() -> {
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
if (gd instanceof CGraphicsDevice) {
((CGraphicsDevice) gd).updateDisplayParameters(displayConfiguration);
}
}
});
}
break;
default:

View File

@@ -0,0 +1,80 @@
/*
* 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 com.jetbrains.desktop;
import com.jetbrains.desktop.image.TextureWrapperSurfaceManager;
import com.jetbrains.exported.JBRApi;
import sun.awt.image.SurfaceManager;
import sun.java2d.SurfaceData;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.metal.MTLTextureWrapperSurfaceData;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
@JBRApi.Service
@JBRApi.Provides("SharedTextures")
public class SharedTexturesService extends SharedTextures {
private final int textureType;
public SharedTexturesService() {
textureType = getTextureTypeImpl();
if (textureType == UNDEFINED_TEXTURE_TYPE) {
throw new JBRApi.ServiceNotAvailableException();
}
}
@Override
public int getTextureType() {
return textureType;
}
private static int getTextureTypeImpl() {
GraphicsConfiguration gc = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration();
if (gc instanceof MTLGraphicsConfig) {
return METAL_TEXTURE_TYPE;
}
return 0;
}
@Override
protected SurfaceManager createSurfaceManager(GraphicsConfiguration gc, Image image, long texture) {
SurfaceData sd;
if (gc instanceof MTLGraphicsConfig mtlGraphicsConfig) {
sd = new MTLTextureWrapperSurfaceData(mtlGraphicsConfig, image, texture);
} else {
throw new IllegalArgumentException("Unsupported graphics configuration: " + gc);
}
return new TextureWrapperSurfaceManager(sd);
}
}

View File

@@ -34,18 +34,21 @@ import java.awt.Window;
import java.awt.geom.Rectangle2D;
import java.awt.peer.WindowPeer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.MacOSFlags;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.opengl.CGLGraphicsConfig;
import sun.lwawt.macosx.CThreading;
import sun.util.logging.PlatformLogger;
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
public final class CGraphicsDevice extends GraphicsDevice
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
@@ -67,7 +70,7 @@ public final class CGraphicsDevice extends GraphicsDevice
private DisplayMode originalMode;
private DisplayMode initialMode;
public CGraphicsDevice(final int displayID) {
public CGraphicsDevice(final int displayID, DisplayConfiguration config) {
this.displayID = displayID;
this.initialMode = getDisplayMode();
StringBuilder errorMessage = new StringBuilder();
@@ -91,7 +94,7 @@ public final class CGraphicsDevice extends GraphicsDevice
}
// [JBR] we don't call displayChanged after creating a device, so call it here.
displayChanged();
updateDevice(config);
}
int getDisplayID() {
@@ -174,8 +177,6 @@ public final class CGraphicsDevice extends GraphicsDevice
yResolution = nativeGetYResolution(displayID);
isMirroring = nativeIsMirroring(displayID);
bounds = nativeGetBounds(displayID).getBounds(); //does integer rounding
screenInsets = nativeGetScreenInsets(displayID);
initScaleFactor();
resizeFSWindow(getFullScreenWindow(), bounds);
//TODO configs?
}
@@ -183,29 +184,43 @@ public final class CGraphicsDevice extends GraphicsDevice
/**
* @return false if display parameters were changed, so we need to recreate the device.
*/
boolean updateDevice() {
boolean updateDevice(DisplayConfiguration config) {
int s = scale;
double xr = xResolution, yr = yResolution;
boolean m = isMirroring;
var b = bounds;
updateDisplayParameters(config);
displayChanged();
return s == scale && xr == xResolution && yr == yResolution && m == isMirroring && b.equals(bounds);
}
public void displayParametersChanged() {
Insets newScreenInsets = nativeGetScreenInsets(displayID);
if (!newScreenInsets.equals(screenInsets)) {
public void updateDisplayParameters(DisplayConfiguration config) {
Descriptor desc = config.getDescriptor(displayID);
if (desc == null) return;
if (!desc.screenInsets.equals(screenInsets)) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Screen insets for display(" + displayID + ") changed " +
"[top=" + screenInsets.top + ",left=" + screenInsets.left +
",bottom=" + screenInsets.bottom + ",right=" + screenInsets.right +
"]->[top=" + newScreenInsets.top + ",left=" + newScreenInsets.left +
",bottom=" + newScreenInsets.bottom + ",right=" + newScreenInsets.right +
"]->[top=" + desc.screenInsets.top + ",left=" + desc.screenInsets.left +
",bottom=" + desc.screenInsets.bottom + ",right=" + desc.screenInsets.right +
"]");
}
screenInsets = newScreenInsets;
screenInsets = desc.screenInsets;
}
int newScale = 1;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
newScale = (int) (debugScale >= 1 ? Math.round(debugScale) : (int) desc.scale);
}
if (newScale != scale) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Scale for display(" + displayID + ") changed " + scale + "->" + newScale);
}
scale = newScale;
}
}
@Override
public void paletteChanged() {
// devices do not need to react to this event.
@@ -352,23 +367,6 @@ public final class CGraphicsDevice extends GraphicsDevice
}
}
private void initScaleFactor() {
int _scale = scale;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
scale = (int) (debugScale >= 1
? Math.round(debugScale)
: nativeGetScaleFactor(displayID));
} else {
scale = 1;
}
if (_scale != scale && logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("current scale = " + _scale + ", new scale = " + scale + " (" + this + ")");
}
}
private static native double nativeGetScaleFactor(int displayID);
private static native void nativeResetDisplayMode();
private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);
@@ -383,7 +381,37 @@ public final class CGraphicsDevice extends GraphicsDevice
private static native boolean nativeIsMirroring(int displayID);
private static native Insets nativeGetScreenInsets(int displayID);
private static native Rectangle2D nativeGetBounds(int displayID);
private static native void nativeGetDisplayConfiguration(DisplayConfiguration config);
public static final class DisplayConfiguration {
private final Map<Integer, Descriptor> map = new HashMap<>();
private void addDescriptor(int displayID, int top, int left, int bottom, int right, double scale) {
map.put(displayID, new Descriptor(new Insets(top, left, bottom, right), scale));
}
public Descriptor getDescriptor(int displayID) {
return map.get(displayID);
}
public static DisplayConfiguration get() {
try {
return CThreading.executeOnAppKit(() -> {
DisplayConfiguration config = new DisplayConfiguration();
nativeGetDisplayConfiguration(config);
return config;
});
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
private static final class Descriptor {
private final Insets screenInsets;
private final double scale;
private Descriptor(Insets screenInsets, double scale) {
this.screenInsets = screenInsets;
this.scale = scale;
}
}
}

View File

@@ -245,6 +245,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
devices.clear();
mainDisplayID = getMainDisplayID();
CGraphicsDevice.DisplayConfiguration config = CGraphicsDevice.DisplayConfiguration.get();
// initialization of the graphics device may change list of displays on
// hybrid systems via an activation of discrete video.
@@ -252,7 +253,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
// of displays, and then recheck the main display again.
if (!old.containsKey(mainDisplayID)) {
try {
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID));
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID, config));
} catch (IllegalStateException e) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Unable to initialize graphics device for displayID=" +
@@ -268,13 +269,13 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
}
for (int id : displayIDs) {
old.compute(id, (i, d) -> {
if (d != null && d.updateDevice()) {
if (d != null && d.updateDevice(config)) {
// Device didn't change -> reuse
devices.put(i, d);
return null;
} else {
// Device changed -> create new
devices.put(i, new CGraphicsDevice(i));
devices.put(i, new CGraphicsDevice(i, config));
return d;
}
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@ import sun.awt.CGraphicsEnvironment;
import sun.awt.image.OffScreenImage;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.SurfaceManager;
import sun.awt.image.TextureWrapperSurfaceManager;
import sun.awt.image.VolatileSurfaceManager;
import sun.java2d.Disposer;
import sun.java2d.DisposerRecord;
@@ -49,7 +48,6 @@ import java.awt.BufferCapabilities;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.Rectangle;
@@ -71,7 +69,7 @@ import static sun.java2d.pipe.hw.ContextCapabilities.*;
import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER;
public final class MTLGraphicsConfig extends CGraphicsConfig
implements AccelGraphicsConfig, SurfaceManager.Factory, SurfaceManager.TextureWrapperFactory
implements AccelGraphicsConfig, SurfaceManager.Factory
{
private static ImageCapabilities imageCaps = new MTLImageCaps();
@@ -380,11 +378,4 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
Object context) {
return new MTLVolatileSurfaceManager(image, context);
}
@Override
public SurfaceManager createTextureWrapperSurfaceManager(
GraphicsConfiguration gc, Image image, long texture) {
SurfaceData sd = MTLSurfaceData.createData(this, image, texture);
return new TextureWrapperSurfaceManager(sd);
}
}

View File

@@ -50,7 +50,6 @@ import java.awt.Transparency;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.util.concurrent.atomic.AtomicBoolean;
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_SURFACE;
import static sun.java2d.pipe.BufferedOpCodes.FLUSH_SURFACE;
@@ -152,7 +151,7 @@ public abstract class MTLSurfaceData extends SurfaceData
private native void initOps(MTLGraphicsConfig gc, long pConfigInfo, long pPeerData, long layerPtr,
int xoff, int yoff, boolean isOpaque);
private MTLSurfaceData(MTLLayer layer, MTLGraphicsConfig gc,
protected MTLSurfaceData(MTLLayer layer, MTLGraphicsConfig gc,
ColorModel cm, int type, int width, int height)
{
super(getCustomSurfaceType(type), cm);
@@ -201,10 +200,6 @@ public abstract class MTLSurfaceData extends SurfaceData
type);
}
public static MTLTextureWrapperSurfaceData createData(MTLGraphicsConfig gc, Image image, long pTexture) {
return new MTLTextureWrapperSurfaceData(gc, image, pTexture);
}
@Override
public double getDefaultScaleX() {
return scale;
@@ -224,8 +219,6 @@ public abstract class MTLSurfaceData extends SurfaceData
protected native boolean initTexture(long pData, boolean isOpaque, int width, int height);
protected native boolean initWithTexture(long pData, boolean isOpaque, long texturePtr);
protected native boolean initRTexture(long pData, boolean isOpaque, int width, int height);
protected native boolean initFlipBackbuffer(long pData, boolean isOpaque, int width, int height);
@@ -681,46 +674,4 @@ public abstract class MTLSurfaceData extends SurfaceData
}
private static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
/**
* Surface data for an existing texture
*/
public static final class MTLTextureWrapperSurfaceData extends MTLSurfaceData {
private final Image myImage;
private MTLTextureWrapperSurfaceData(MTLGraphicsConfig gc, Image image, long pTexture) throws IllegalArgumentException {
super(null, gc, ColorModel.getRGBdefault(), RT_TEXTURE, /*width=*/ 0, /*height=*/ 0);
myImage = image;
MTLRenderQueue rq = MTLRenderQueue.getInstance();
AtomicBoolean success = new AtomicBoolean(false);
rq.lock();
try {
MTLContext.setScratchSurface(gc);
rq.flushAndInvokeNow(() -> success.set(initWithTexture(getNativeOps(), false, pTexture)));
} finally {
rq.unlock();
}
if (!success.get()) {
throw new IllegalArgumentException("Failed to init the surface data");
}
}
@Override
public SurfaceData getReplacement() {
throw new UnsupportedOperationException("not implemented");
}
@Override
public Object getDestination() {
return myImage;
}
@Override
public Rectangle getBounds() {
return getNativeBounds();
}
}
}

View File

@@ -0,0 +1,9 @@
package sun.java2d.metal;
public class MTLSurfaceDataExt {
public static boolean initWithTexture(MTLSurfaceData sd, long texturePtr) {
return initWithTexture(sd.getNativeOps(), false, texturePtr);
}
private static native boolean initWithTexture(long pData, boolean isOpaque, long texturePtr);
}

View File

@@ -0,0 +1,49 @@
package sun.java2d.metal;
import sun.java2d.SurfaceData;
import java.awt.*;
import java.awt.image.ColorModel;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Surface data for an existing texture
*/
public final class MTLTextureWrapperSurfaceData extends MTLSurfaceData {
private final Image myImage;
public MTLTextureWrapperSurfaceData(MTLGraphicsConfig gc, Image image, long pTexture) throws IllegalArgumentException {
super(null, gc, gc.getColorModel(TRANSLUCENT), RT_TEXTURE, /*width=*/ 0, /*height=*/ 0);
myImage = image;
MTLRenderQueue rq = MTLRenderQueue.getInstance();
AtomicBoolean success = new AtomicBoolean(false);
rq.lock();
try {
MTLContext.setScratchSurface(gc);
rq.flushAndInvokeNow(() -> success.set(MTLSurfaceDataExt.initWithTexture(this, pTexture)));
} finally {
rq.unlock();
}
if (!success.get()) {
throw new IllegalArgumentException("Failed to init the surface data");
}
}
@Override
public SurfaceData getReplacement() {
throw new UnsupportedOperationException("not implemented");
}
@Override
public Object getDestination() {
return myImage;
}
@Override
public Rectangle getBounds() {
return getNativeBounds();
}
}

View File

@@ -45,7 +45,6 @@ import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.peer.ComponentPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -1066,33 +1065,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
return isFullScreenMode;
}
private void waitForWindowState(int state) {
if (peer.getState() == state) {
return;
}
Object lock = new Object();
WindowStateListener wsl = new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
synchronized (lock) {
if (e.getNewState() == state) {
lock.notifyAll();
}
}
}
};
target.addWindowStateListener(wsl);
if (peer.getState() != state) {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException ie) {}
}
}
target.removeWindowStateListener(wsl);
}
@Override
public void setWindowState(int windowState) {
if (peer == null || !peer.isVisible()) {
@@ -1114,7 +1086,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// let's return into the normal states first
// the zoom call toggles between the normal and the max states
unmaximize();
waitForWindowState(Frame.NORMAL);
}
execute(CWrapper.NSWindow::miniaturize);
break;
@@ -1122,7 +1093,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
if (prevWindowState == Frame.ICONIFIED) {
// let's return into the normal states first
execute(CWrapper.NSWindow::deminiaturize);
waitForWindowState(Frame.NORMAL);
}
maximize();
break;

View File

@@ -363,47 +363,6 @@ Java_sun_awt_CGraphicsDevice_nativeGetBounds
return CGToJavaRect(env, rect);
}
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetScreenInsets
* Signature: (I)D
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets
(JNIEnv *env, jclass class, jint displayID)
{
jobject ret = NULL;
__block NSRect frame = NSZeroRect;
__block NSRect visibleFrame = NSZeroRect;
JNI_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
if ([screenID unsignedIntValue] == displayID){
frame = [screen frame];
visibleFrame = [screen visibleFrame];
break;
}
}
}];
// Convert between Cocoa's coordinate system and Java.
jint bottom = visibleFrame.origin.y - frame.origin.y;
jint top = frame.size.height - visibleFrame.size.height - bottom;
jint left = visibleFrame.origin.x - frame.origin.x;
jint right = frame.size.width - visibleFrame.size.width - left;
DECLARE_CLASS_RETURN(jc_Insets, "java/awt/Insets", ret);
DECLARE_METHOD_RETURN(jc_Insets_ctor, jc_Insets, "<init>", "(IIII)V", ret);
ret = (*env)->NewObject(env, jc_Insets, jc_Insets_ctor, top, left, bottom, right);
JNI_COCOA_EXIT(env);
return ret;
}
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeResetDisplayMode
@@ -557,31 +516,40 @@ Java_sun_awt_CGraphicsDevice_nativeGetDisplayModes
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetScaleFactor
* Signature: (I)D
* Method: nativeGetDisplayConfiguration
* Signature: (Lsun/awt/CGraphicsDevice$DisplayConfiguration;)V
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScaleFactor
(JNIEnv *env, jclass class, jint displayID)
{
__block jdouble ret = 1.0f;
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayConfiguration
(JNIEnv *env, jclass class, jobject config) {
AWT_ASSERT_APPKIT_THREAD;
JNI_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
if ([screenID unsignedIntValue] == displayID){
if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
ret = [screen backingScaleFactor];
}
break;
}
DECLARE_CLASS(jc_DisplayConfiguration, "sun/awt/CGraphicsDevice$DisplayConfiguration");
DECLARE_METHOD(jc_DisplayConfiguration_addDescriptor, jc_DisplayConfiguration, "addDescriptor", "(IIIIID)V");
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
jint displayID = [screenID unsignedIntValue];
jdouble scale = 1.0;
if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
scale = [screen backingScaleFactor];
}
}];
NSRect frame = [screen frame];
NSRect visibleFrame = [screen visibleFrame];
// Convert between Cocoa's coordinate system and Java.
jint bottom = visibleFrame.origin.y - frame.origin.y;
jint top = frame.size.height - visibleFrame.size.height - bottom;
jint left = visibleFrame.origin.x - frame.origin.x;
jint right = frame.size.width - visibleFrame.size.width - left;
(*env)->CallVoidMethod(env, config, jc_DisplayConfiguration_addDescriptor,
displayID, top, left, bottom, right, scale);
CHECK_EXCEPTION();
}
JNI_COCOA_EXIT(env);
return ret;
}

View File

@@ -116,6 +116,7 @@ static void displaycb_handle
(CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo)
{
AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
JNI_COCOA_ENTER(env);
if (TRACE_DISPLAY_CALLBACKS) {
@@ -152,7 +153,6 @@ JNI_COCOA_ENTER(env);
block:^()
{
@try {
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef);
if (graphicsEnv == NULL) return; // ref already GC'd
DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
@@ -173,7 +173,6 @@ JNI_COCOA_ENTER(env);
// braces to reduce variable scope
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef);
if (graphicsEnv == NULL) return; // ref already GC'd
DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");

View File

@@ -311,11 +311,11 @@ static const struct SymbolicHotKey defaultSymbolicHotKeys[] = {
[Shortcut_FullScreenTileRight] = { "FullScreenTileRight", "Windows: Full-Screen Tile Right", YES, 65535, 65535, 0, 15, 4 },
};
static const int numSymbolicHotkeys = sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]);
#define NUM_SYMBOLIC_HOTKEYS (sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]))
static struct SystemHotkeyState {
bool symbolicHotkeysFilled;
struct SymbolicHotKey currentSymbolicHotkeys[numSymbolicHotkeys];
struct SymbolicHotKey currentSymbolicHotkeys[NUM_SYMBOLIC_HOTKEYS];
bool initialized;
bool enabled;
@@ -398,7 +398,7 @@ static void visitServicesShortcut(Visitor visitorBlock, NSString * key_equivalen
visitorBlock(-1, keyChar.UTF8String, modifiers, desc.UTF8String, -1, NULL);
}
static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS]) {
// Called from the main thread
@try {
@@ -425,7 +425,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
return;
}
memcpy(hotkeys, defaultSymbolicHotKeys, numSymbolicHotkeys * sizeof(struct SymbolicHotKey));
memcpy(hotkeys, defaultSymbolicHotKeys, NUM_SYMBOLIC_HOTKEYS * sizeof(struct SymbolicHotKey));
for (id keyObj in hkObj) {
if (![keyObj isKindOfClass:[NSString class]]) {
@@ -438,7 +438,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
int uid = [hkNumber intValue];
// Ignore hotkeys out of range, as well as 0, which is the "invalid value" for intValue
if (uid <= 0 || uid >= numSymbolicHotkeys) {
if (uid <= 0 || uid >= NUM_SYMBOLIC_HOTKEYS) {
continue;
}
@@ -512,7 +512,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
}
static void updateAppleSymbolicHotkeysCache() {
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
readAppleSymbolicHotkeys(hotkeys);
pthread_mutex_lock(&state.mutex);
@@ -521,10 +521,10 @@ static void updateAppleSymbolicHotkeysCache() {
pthread_mutex_unlock(&state.mutex);
}
static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys], Visitor visitorBlock) {
static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS], Visitor visitorBlock) {
const NSOperatingSystemVersion macOSVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
for (int uid = 0; uid < numSymbolicHotkeys; ++uid) {
for (int uid = 0; uid < NUM_SYMBOLIC_HOTKEYS; ++uid) {
struct SymbolicHotKey* hotkey = &hotkeys[uid];
if (!hotkey->enabled) {
@@ -646,12 +646,12 @@ static bool ensureInitializedAndEnabled() {
return true;
}
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
pthread_mutex_lock(&state.mutex);
if (state.symbolicHotkeysFilled) {
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
}
pthread_mutex_unlock(&state.mutex);
}
@@ -661,7 +661,7 @@ static void readSystemHotkeysImpl(Visitor visitorBlock) {
return;
}
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
readAppleSymbolicHotkeysCached(hotkeys);
iterateAppleSymbolicHotkeys(hotkeys, visitorBlock);

View File

@@ -67,9 +67,17 @@ static jclass sjc_CAccessibility = NULL;
jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
sjm_getCurrentAccessiblePopupMenu,
fAccessible, fComponent);
CHECK_EXCEPTION();
if (axComponent == NULL) {
return nil;
}
CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:axComponent
withEnv:env withView:self->fView isCurrent:YES];
(*env)->DeleteLocalRef(env, axComponent);
if (currentElement == nil) {
return nil;
}
NSArray *children = [CommonComponentAccessibility childrenOfParent:currentElement
withEnv:env

View File

@@ -112,6 +112,13 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
NSLock* _lock;
}
+ (NSUInteger) getDrawableId:(id<MTLDrawable>)mtlDrawable {
if (@available(macOS 10.15.4, *)) {
return [mtlDrawable drawableID];
}
return -1;
}
- (id) initWithJavaLayer:(jobject)layer usePerfCounters:(jboolean)perfCountersEnabled
{
AWT_ASSERT_APPKIT_THREAD;
@@ -246,12 +253,12 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
#if TRACE_DISPLAY_ON
self.avgNextDrawableTime = nextDrawableLatency * a + self.avgNextDrawableTime * (1.0 - a);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
CACurrentMediaTime(), mtlDrawable.drawableID,
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
CACurrentMediaTime(), [MTLLayer getDrawableId:mtlDrawable],
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
);
#endif
}
// Keep Fence from now:
@@ -284,7 +291,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) presented"
" - presentedHandlerLatency = %.3lf ms frameInterval = %.3lf ms",
CACurrentMediaTime(), drawable.drawableID,
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
1000.0 * presentedHandlerLatency, 1000.0 * frameInterval
);
self.lastPresentedTime = presentedTime;
@@ -299,7 +306,8 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) skipped"
" - presentedHandlerLatency = %.3lf ms",
CACurrentMediaTime(), drawable.drawableID, 1000.0 * presentedHandlerLatency
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
1000.0 * presentedHandlerLatency
);
}
}
@@ -309,7 +317,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
// Present drawable:
NSUInteger drawableId = -1;
if (TRACE_DISPLAY) {
drawableId = mtlDrawable.drawableID;
drawableId = [MTLLayer getDrawableId:mtlDrawable];
J2dRlsTraceLn(J2D_TRACE_INFO,
"[%.6lf] MTLLayer.blitTexture: layer[%p] present drawable(%d)",
CACurrentMediaTime(), self, drawableId);

View File

@@ -107,81 +107,6 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque
}
}
static jboolean MTLSurfaceData_initWithTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque, void* pTexture) {
@autoreleasepool {
if (bmtlsdo == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: ops are null");
return JNI_FALSE;
}
if (pTexture == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: texture is null");
return JNI_FALSE;
}
id <MTLTexture> texture = (__bridge id <MTLTexture>) pTexture;
if (texture == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: failed to cast texture to MTLTexture");
return JNI_FALSE;
}
if (texture.width >= MTL_GPU_FAMILY_MAC_TXT_SIZE || texture.height >= MTL_GPU_FAMILY_MAC_TXT_SIZE ||
texture.width == 0 || texture.height == 0) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: wrong texture size %d x %d",
texture.width, texture.height);
return JNI_FALSE;
}
if (texture.pixelFormat != MTLPixelFormatBGRA8Unorm) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: unsupported pixel format: %d",
texture.pixelFormat);
return JNI_FALSE;
}
bmtlsdo->pTexture = texture;
bmtlsdo->pOutTexture = NULL;
MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
if (mtlsdo == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: MTLSDOps are null");
return JNI_FALSE;
}
if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: MTLSDOps wasn't initialized (context is null)");
return JNI_FALSE;
}
MTLContext* ctx = mtlsdo->configInfo->context;
MTLTextureDescriptor *stencilDataDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint
width:texture.width
height:texture.height
mipmapped:NO];
stencilDataDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
stencilDataDescriptor.storageMode = MTLStorageModePrivate;
bmtlsdo->pStencilData = [ctx.device newTextureWithDescriptor:stencilDataDescriptor];
MTLTextureDescriptor *stencilTextureDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatStencil8
width:texture.width
height:texture.height
mipmapped:NO];
stencilTextureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
stencilTextureDescriptor.storageMode = MTLStorageModePrivate;
bmtlsdo->pStencilTexture = [ctx.device newTextureWithDescriptor:stencilTextureDescriptor];
bmtlsdo->isOpaque = isOpaque;
bmtlsdo->width = texture.width;
bmtlsdo->height = texture.height;
bmtlsdo->drawableType = MTLSD_RT_TEXTURE;
[texture retain];
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d sfType=%d",
bmtlsdo->width, bmtlsdo->height, bmtlsdo, bmtlsdo->pTexture, isOpaque, bmtlsdo->drawableType);
return JNI_TRUE;
}
}
/**
* Initializes an MTL texture, using the given width and height as
* a guide.
@@ -198,19 +123,6 @@ Java_sun_java2d_metal_MTLSurfaceData_initTexture(
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL
Java_sun_java2d_metal_MTLSurfaceData_initWithTexture(
JNIEnv *env, jobject mtlds,
jlong pData, jboolean isOpaque,
jlong pTexture) {
BMTLSDOps *bmtlsdops = (BMTLSDOps *) pData;
if (!MTLSurfaceData_initWithTexture(bmtlsdops, isOpaque, jlong_to_ptr(pTexture))) {
return JNI_FALSE;
}
MTLSD_SetNativeDimensions(env, (BMTLSDOps *) pData, bmtlsdops->width, bmtlsdops->height);
return JNI_TRUE;
}
/**
* Initializes a framebuffer object, using the given width and height as
* a guide. See MTLSD_InitTextureObject() and MTLSD_initRTexture()

View File

@@ -0,0 +1,102 @@
#import "MTLSurfaceData.h"
#import "jni_util.h"
// From MTLSurfaceData.m
extern void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *bmtlsdo, jint w, jint h);
static jboolean MTLSurfaceData_initWithTexture(
BMTLSDOps *bmtlsdo,
jboolean isOpaque,
void* pTexture
) {
@autoreleasepool {
if (bmtlsdo == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: ops are null");
return JNI_FALSE;
}
if (pTexture == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: texture is null");
return JNI_FALSE;
}
id <MTLTexture> texture = (__bridge id <MTLTexture>) pTexture;
if (texture == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: failed to cast texture to MTLTexture");
return JNI_FALSE;
}
if (texture.width >= MTL_GPU_FAMILY_MAC_TXT_SIZE || texture.height >= MTL_GPU_FAMILY_MAC_TXT_SIZE ||
texture.width == 0 || texture.height == 0) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: wrong texture size %d x %d",
texture.width, texture.height);
return JNI_FALSE;
}
if (texture.pixelFormat != MTLPixelFormatBGRA8Unorm) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: unsupported pixel format: %d",
texture.pixelFormat);
return JNI_FALSE;
}
bmtlsdo->pTexture = texture;
bmtlsdo->pOutTexture = NULL;
MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
if (mtlsdo == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: MTLSDOps are null");
return JNI_FALSE;
}
if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initWithTexture: MTLSDOps wasn't initialized (context is null)");
return JNI_FALSE;
}
MTLContext* ctx = mtlsdo->configInfo->context;
MTLTextureDescriptor *stencilDataDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint
width:texture.width
height:texture.height
mipmapped:NO];
stencilDataDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
stencilDataDescriptor.storageMode = MTLStorageModePrivate;
bmtlsdo->pStencilData = [ctx.device newTextureWithDescriptor:stencilDataDescriptor];
MTLTextureDescriptor *stencilTextureDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatStencil8
width:texture.width
height:texture.height
mipmapped:NO];
stencilTextureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
stencilTextureDescriptor.storageMode = MTLStorageModePrivate;
bmtlsdo->pStencilTexture = [ctx.device newTextureWithDescriptor:stencilTextureDescriptor];
bmtlsdo->isOpaque = isOpaque;
bmtlsdo->width = texture.width;
bmtlsdo->height = texture.height;
bmtlsdo->drawableType = MTLSD_RT_TEXTURE;
[texture retain];
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d sfType=%d",
bmtlsdo->width, bmtlsdo->height, bmtlsdo, bmtlsdo->pTexture, isOpaque, bmtlsdo->drawableType);
return JNI_TRUE;
}
}
JNIEXPORT jboolean JNICALL
Java_sun_java2d_metal_MTLSurfaceDataExt_initWithTexture(
JNIEnv *env,
jclass cls,
jlong pData,
jboolean isOpaque,
jlong pTexture
) {
BMTLSDOps *bmtlsdops = (BMTLSDOps *) pData;
if (!MTLSurfaceData_initWithTexture(bmtlsdops, isOpaque, jlong_to_ptr(pTexture))) {
return JNI_FALSE;
}
MTLSD_SetNativeDimensions(env, (BMTLSDOps *) pData, bmtlsdops->width, bmtlsdops->height);
return JNI_TRUE;
}

View File

@@ -254,8 +254,11 @@ AWT_ASSERT_APPKIT_THREAD;
* Note : if waiting cross-thread, possibly the stack allocated copy is accessible ?
*/
+ (void)invokeBlockCopy:(void (^)(void))blockCopy {
blockCopy();
Block_release(blockCopy);
@try {
blockCopy();
} @finally {
Block_release(blockCopy);
}
}
+ (NSString*)getCaller:(NSString*)prefixSymbol {
@@ -780,9 +783,18 @@ JNIEXPORT void lwc_plog(JNIEnv* env, const char *formatMsg, ...) {
const NSUInteger count = [self.queue count];
if (count != 0) {
for (NSUInteger i = 0; i < count; i++) {
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
// invoke callback:
[ThreadUtilities invokeBlockCopy:blockCopy];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try {
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
// invoke callback:
[ThreadUtilities invokeBlockCopy:blockCopy];
} @catch (NSException *exception) {
// handle any exception to avoid crashing the main run loop:
NSLog(@"Apple AWT Cocoa Exception: %@", [exception description]);
NSLog(@"Apple AWT Cocoa Exception callstack: %@", [exception callStackSymbols]);
} @finally {
[pool drain];
}
}
// reset queue anyway:
[self reset];

View File

@@ -26,52 +26,19 @@
package com.jetbrains.desktop;
import com.jetbrains.desktop.image.TextureWrapperImage;
import com.jetbrains.exported.JBRApi;
import sun.awt.SunToolkit;
import sun.awt.image.SurfaceManager;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.*;
@JBRApi.Service
@JBRApi.Provides("SharedTextures")
public class SharedTextures {
public abstract class SharedTextures {
public final static int UNDEFINED_TEXTURE_TYPE = 0;
public final static int METAL_TEXTURE_TYPE = 1;
private final int textureType;
public abstract int getTextureType();
public static SharedTextures create() {
return new SharedTextures();
public final Image wrapTexture(GraphicsConfiguration gc, long texture) {
return new TextureWrapperImage((img) -> createSurfaceManager(gc, img, texture));
}
private SharedTextures() {
textureType = getTextureTypeImpl();
if (textureType == 0) {
throw new JBRApi.ServiceNotAvailableException();
}
}
public int getTextureType() {
return textureType;
}
public Image wrapTexture(GraphicsConfiguration gc, long texture) {
return new TextureWrapperImage(gc, texture);
}
private static int getTextureTypeImpl() {
GraphicsConfiguration gc = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration();
try {
if (SunToolkit.isInstanceOf(gc, "sun.java2d.metal.MTLGraphicsConfig")) {
return METAL_TEXTURE_TYPE;
}
} catch (Exception e) {
throw new InternalError("Unexpected exception during reflection", e);
}
return 0;
}
protected abstract SurfaceManager createSurfaceManager(GraphicsConfiguration gc, Image image, long texture);
}

View File

@@ -37,6 +37,7 @@ import java.awt.ImageCapabilities;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.util.function.Function;
/**
* This class is a wrapper for a GPU texture-based image.
@@ -51,31 +52,14 @@ import java.awt.image.ImageProducer;
* the surface flushing.
*/
public class TextureWrapperImage extends Image {
final GraphicsConfiguration gc;
final SurfaceData sd;
final static ImageCapabilities capabilities = new ImageCapabilities(true);
/**
* Constructs a TextureWrapperImage instance with the specified graphics configuration
* and a texture.
*
* @param gc the graphics configuration
* @param texture the texture that will be wrapped by this instance.
* Platform-specific details:
* macOS (with the Metal rendering pipeline) - a pointer to an MTLTexture object is expected
*
* @throws UnsupportedOperationException if the current pipeline is not supported
* @throws IllegalArgumentException if the texture cannot be wrapped
*/
public TextureWrapperImage(GraphicsConfiguration gc, long texture)
public TextureWrapperImage(Function<Image, SurfaceManager> surfaceManagerFactory)
throws UnsupportedOperationException, IllegalArgumentException {
this.gc = gc;
SurfaceManager surfaceManager;
if (gc instanceof SurfaceManager.TextureWrapperFactory factory) {
surfaceManager = factory.createTextureWrapperSurfaceManager(gc, this, texture);
} else throw new UnsupportedOperationException();
sd = surfaceManager.getPrimarySurfaceData();
SurfaceManager.setManager(this, surfaceManager);
SurfaceManager sm = surfaceManagerFactory.apply(this);
sd = sm.getPrimarySurfaceData();
SurfaceManager.setManager(this, sm);
}
@Override

View File

@@ -23,8 +23,9 @@
* questions.
*/
package sun.awt.image;
package com.jetbrains.desktop.image;
import sun.awt.image.SurfaceManager;
import sun.java2d.SurfaceData;
import java.awt.GraphicsConfiguration;

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

@@ -1,36 +0,0 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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;
import java.util.EventListener;
public interface DisplayParametersChangedListener extends EventListener {
/**
* Invoked when the display parameters changed.
*/
public void displayParametersChanged();
}

View File

@@ -184,14 +184,6 @@ public abstract class SurfaceManager {
}
}
/**
* See TextureWrapperImage.
*/
public interface TextureWrapperFactory {
SurfaceManager createTextureWrapperSurfaceManager(
GraphicsConfiguration gc, Image image, long texture);
}
/**
* An interface for GraphicsConfiguration objects to implement if
* they create their own VolatileSurfaceManager implementations.

View File

@@ -44,7 +44,6 @@ import java.util.Locale;
import java.util.TreeMap;
import sun.awt.DisplayChangedListener;
import sun.awt.DisplayParametersChangedListener;
import sun.awt.SunDisplayChanger;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
@@ -60,7 +59,7 @@ import sun.java2d.pipe.Region;
* @see GraphicsConfiguration
*/
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
@@ -276,15 +275,6 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
displayChanger.notifyListeners();
}
@Override
public void displayParametersChanged() {
for (GraphicsDevice gd : getScreenDevices()) {
if (gd instanceof DisplayParametersChangedListener) {
((DisplayParametersChangedListener) gd).displayParametersChanged();
}
}
}
/**
* Part of the DisplayChangedListener interface:
* propagate this event to listeners

View File

@@ -1944,10 +1944,15 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
awtLock();
try {
if (numberOfButtons == 0) {
if (XdgDesktopPortal.isRemoteDesktop()
&& ScreencastHelper.isAvailable()) {
numberOfButtons = 3;
} else {
// The commented-out code is introduced in 8351907 and causes inability to use
// any mouse extra buttons under XWayland GNOME of version >= 47,
// thus causing JBR-9713, JBR-9714, JBR-9715.
// Please don't enable it back until a proper fix appears in OpenJDK.
//
//if (XdgDesktopPortal.isRemoteDesktop()
// && ScreencastHelper.isAvailable()) {
// numberOfButtons = 3;
//} else {
numberOfButtons = getNumberOfButtonsImpl();
numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons;
//4th and 5th buttons are for wheel and shouldn't be reported as buttons.
@@ -1959,7 +1964,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
} else if (numberOfButtons == 4 || numberOfButtons == 5) {
numberOfButtons = 3;
}
}
//}
}
//Assume don't have to re-query the number again and again.
return numberOfButtons;

View File

@@ -26,7 +26,6 @@ package sun.awt.wl;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
@@ -130,5 +129,7 @@ public abstract class FrameDecoration {
return null;
}
public abstract void notifyNativeWindowCreated(long nativePtr);
public abstract void notifyNativeWindowToBeHidden(long nativePtr);
public abstract void dispose();
}

View File

@@ -294,6 +294,14 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
return null;
}
@Override
public void notifyNativeWindowCreated(long nativePtr) {
}
@Override
public void notifyNativeWindowToBeHidden(long nativePtr) {
}
@Override
public void dispose() {
WLToolkit.getDefaultToolkit().removePropertyChangeListener("awt.os.theme.isDark", pcl);

View File

@@ -74,6 +74,14 @@ public class MinimalFrameDecoration extends FrameDecoration {
// Nothing to repaint
}
@Override
public void notifyNativeWindowCreated(long nativePtr) {
}
@Override
public void notifyNativeWindowToBeHidden(long nativePtr) {
}
@Override
public void dispose() {
// Nothing to dispose

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2022-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;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
/**
* Decorations based on the xdg-decoration-unstable-v1 protocol.
* Supported iff WLToolkit.isSSDAvailable().
*
* The decoration itself is added by the server on a surface separate from the window itself,
* so the window acts as if it is undecorated. For example, there are no insets, no special
* repainting is done, etc.
*/
public class ServerSideFrameDecoration extends FrameDecoration {
private long nativeDecorPtr;
public ServerSideFrameDecoration(WLDecoratedPeer peer) {
super(peer);
}
@Override
public Insets getContentInsets() {
return new Insets(0, 0, 0, 0);
}
@Override
public Rectangle getTitleBarBounds() {
return new Rectangle(0, 0, 0, 0);
}
@Override
public Dimension getMinimumSize() {
return new Dimension(0, 0);
}
@Override
public void paint(Graphics g) {
// Nothing to paint here, the Wayland server provides all the painting
}
@Override
public void notifyConfigured(boolean active, boolean maximized, boolean fullscreen) {
}
@Override
public boolean isRepaintNeeded() {
return false;
}
@Override
public void markRepaintNeeded(boolean value) {
// Nothing to repaint
}
@Override
public void notifyNativeWindowCreated(long nativePtr) {
if (!peer.targetIsWlPopup()) {
nativeDecorPtr = createToplevelDecorationImpl(nativePtr);
}
}
@Override
public void notifyNativeWindowToBeHidden(long nativePtr) {
if (nativeDecorPtr != 0) {
disposeImpl(nativeDecorPtr);
nativeDecorPtr = 0;
}
}
@Override
public void dispose() {
// Native resources must have been already disposed when the window was hidden
assert nativeDecorPtr == 0;
}
private native long createToplevelDecorationImpl(long nativeFramePtr);
private native void disposeImpl(long nativeDecorPtr);
}

View File

@@ -113,6 +113,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
private boolean repositionPopup = false; // protected by stateLock
private boolean resizePending = false; // protected by stateLock
private static final boolean shadowEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.wl.Shadow", "true"));
static {
initIDs();
}
@@ -121,6 +123,10 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
* Standard peer constructor, with corresponding Component
*/
WLComponentPeer(Component target) {
this(target, true);
}
protected WLComponentPeer(Component target, boolean dropShadow) {
this.target = target;
this.background = target.getBackground();
Dimension size = constrainSize(target.getBounds().getSize());
@@ -135,14 +141,11 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
log.fine("WLComponentPeer: target=" + target + " with size=" + wlSize);
}
boolean shadowEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.wl.Shadow", "true"));
if (shadowEnabled) {
if (dropShadow && shadowEnabled) {
shadow = new ShadowImpl(targetIsWlPopup() ? ShadowImage.POPUP_SHADOW_SIZE : ShadowImage.WINDOW_SHADOW_SIZE);
} else {
shadow = new NilShadow();
}
// TODO
// setup parent window for target
}
int getDisplayScale() {
@@ -387,6 +390,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
WLRobotPeer.setLocationOfWLSurface(wlSurface, xNative, yNative);
}
notifyNativeWindowCreated(nativePtr);
shadow.createSurface();
// From xdg-shell.xml: "After creating a role-specific object and
@@ -394,6 +399,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
// without any buffer attached"
shadow.commitSurface();
wlSurface.commit();
if (!isWlPopup && target.getParent() != null) activate();
((WLToolkit) Toolkit.getDefaultToolkit()).flush();
});
@@ -404,6 +410,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
} else {
performLocked(() -> {
if (wlSurface != null) { // may get a "hide" request even though we were never shown
notifyNativeWindowToBeHidden(nativePtr);
nativeHideFrame(nativePtr);
shadow.hide();
@@ -414,6 +422,12 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
}
}
protected void notifyNativeWindowCreated(long nativePtr) {
}
protected void notifyNativeWindowToBeHidden(long nativePtr) {
}
/**
* Returns true if our target should be treated as a popup in Wayland's sense,
* i.e. it has to have a parent to position relative to.
@@ -440,6 +454,10 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
shadow.updateSurfaceData();
}
public boolean isResizable() {
return true;
}
@Override
public void updateSurfaceSize() {
assert SunToolkit.isAWTLockHeldByCurrentThread();
@@ -460,9 +478,15 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
wlSurface.updateSurfaceSize(surfaceWidth, surfaceHeight);
nativeSetWindowGeometry(nativePtr, 0, 0, surfaceWidth, surfaceHeight);
nativeSetMinimumSize(nativePtr, surfaceMinSize.width, surfaceMinSize.height);
if (surfaceMaxSize != null) {
nativeSetMaximumSize(nativePtr, surfaceMaxSize.width, surfaceMaxSize.height);
if (isResizable()) {
nativeSetMinimumSize(nativePtr, surfaceMinSize.width, surfaceMinSize.height);
if (surfaceMaxSize != null) {
nativeSetMaximumSize(nativePtr, surfaceMaxSize.width, surfaceMaxSize.height);
}
} else {
// Prevent SSD from resizing windows that are not meant to be resizeable
nativeSetMinimumSize(nativePtr, surfaceWidth, surfaceHeight);
nativeSetMaximumSize(nativePtr, surfaceWidth, surfaceHeight);
}
if (popupNeedsReposition()) {
@@ -875,6 +899,10 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
performLocked(() -> nativeShowWindowMenu(serial, nativePtr, xNative, yNative));
}
void setIcon(int size, int[] pixels) {
performLocked(() -> nativeSetIcon(nativePtr, size, pixels));
}
@Override
public ColorModel getColorModel() {
GraphicsConfiguration graphicsConfig = target.getGraphicsConfiguration();
@@ -1092,15 +1120,20 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
}
private static long getSerialForActivation() {
long serial = WLToolkit.getInputState().keyboardEnterSerial(); // a focus event
if (serial == 0) { // may have just left one surface and not yet entered another
serial = WLToolkit.getInputState().keySerial(); // an input event
}
if (serial == 0) {
// The pointer button serial seems to not work with Mutter, but may work
// with other implementations, so let's keep it as an input event serial
// of the last resort.
serial = WLToolkit.getInputState().pointerButtonSerial();
long serial;
if (WLToolkit.isKDE()) {
serial = WLToolkit.getInputState().latestInputSerial();
} else {
serial = WLToolkit.getInputState().keyboardEnterSerial(); // a focus event
if (serial == 0) { // may have just left one surface and not yet entered another
serial = WLToolkit.getInputState().keySerial(); // an input event
}
if (serial == 0) {
// The pointer button serial seems to not work with Mutter but may work
// with other implementations, so let's keep it as an input event serial
// of the last resort.
serial = WLToolkit.getInputState().pointerButtonSerial();
}
}
return serial;
}
@@ -1138,6 +1171,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
private native void nativeSetMinimumSize(long ptr, int width, int height);
private native void nativeSetMaximumSize(long ptr, int width, int height);
private native void nativeShowWindowMenu(long serial, long ptr, int x, int y);
private native void nativeSetIcon(long ptr, int size, int[] pixels);
static long getNativePtrFor(Component component) {
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();

View File

@@ -68,7 +68,7 @@ public class WLDataOffer {
}
}
public byte[] receiveData(String mime) throws IOException {
public synchronized byte[] receiveData(String mime) throws IOException {
int fd;
if (nativePtr == 0) {
@@ -86,7 +86,7 @@ public class WLDataOffer {
}
}
public void accept(long serial, String mime) {
public synchronized void accept(long serial, String mime) {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
@@ -94,15 +94,17 @@ public class WLDataOffer {
acceptImpl(nativePtr, serial, mime);
}
public void finishDnD() {
public synchronized void finishDnD() {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
finishDnDImpl(nativePtr);
if (selectedAction != 0) {
finishDnDImpl(nativePtr);
}
}
public void setDnDActions(int actions, int preferredAction) {
public synchronized void setDnDActions(int actions, int preferredAction) {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}

View File

@@ -40,10 +40,37 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
private final boolean showMaximize;
private final boolean showMinimize;
private final static String decorationPreference = System.getProperty("sun.awt.wl.WindowDecorationStyle");
private enum DecorationTypePreference {
DEFAULT, // The default decorations painted purely in Java
GTK, // Decorations are painted with the help of GTK (if available)
SERVER; // Wayland server-side decorations (if available)
}
private static final DecorationTypePreference decorationType = determineDecorationPreferenceType();
private static DecorationTypePreference determineDecorationPreferenceType() {
String decorationPreference = System.getProperty("sun.awt.wl.WindowDecorationStyle");
if (decorationPreference != null) {
if ("builtin".equals(decorationPreference)) {
return DecorationTypePreference.DEFAULT;
} else if ("gtk".equals(decorationPreference) && isGTKAvailable()) {
return DecorationTypePreference.GTK;
} else if ("server".equals(decorationPreference) && WLToolkit.isSSDAvailable()) {
return DecorationTypePreference.SERVER;
} else {
return DecorationTypePreference.DEFAULT;
}
} else {
if (!WLToolkit.isKDE() && isGTKAvailable()) {
return DecorationTypePreference.GTK;
} else {
return DecorationTypePreference.DEFAULT;
}
}
}
public WLDecoratedPeer(Window target, boolean isUndecorated, boolean showMinimize, boolean showMaximize) {
super(target);
super(target, decorationType != DecorationTypePreference.SERVER);
this.isUndecorated = isUndecorated;
this.showMinimize = showMinimize;
this.showMaximize = showMaximize;
@@ -54,20 +81,12 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
FrameDecoration d;
if (isUndecorated) {
d = new MinimalFrameDecoration(this);
} else if (decorationPreference != null) {
if ("builtin".equals(decorationPreference)) {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
} else if ("gtk".equals(decorationPreference) && isGTKAvailable()) {
d = new GtkFrameDecoration(this, showMinimize, showMaximize);
} else {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
}
} else {
if (!WLToolkit.isKDE() && isGTKAvailable()) {
d = new GtkFrameDecoration(this, showMinimize, showMaximize);
} else {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
}
d = switch (decorationType) {
case DecorationTypePreference.DEFAULT -> new DefaultFrameDecoration(this, showMinimize, showMaximize);
case DecorationTypePreference.GTK -> new GtkFrameDecoration(this, showMinimize, showMaximize);
case DecorationTypePreference.SERVER -> new ServerSideFrameDecoration(this);
};
}
return d;
}
@@ -84,9 +103,7 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
}
}
public abstract boolean isResizable();
public abstract boolean isInteractivelyResizable();
public abstract boolean isFrameStateSupported(int state);
public abstract void setState(int newState);
public abstract int getState();
@@ -230,4 +247,14 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
getDecoration().dispose();
super.dispose();
}
@Override
protected void notifyNativeWindowCreated(long nativePtr) {
decoration.notifyNativeWindowCreated(nativePtr);
}
@Override
protected void notifyNativeWindowToBeHidden(long nativePtr) {
decoration.notifyNativeWindowToBeHidden(nativePtr);
}
}

View File

@@ -61,7 +61,14 @@ public class WLDragSourceContextPeer extends SunDragSourceContextPeer {
@Override
protected synchronized void handleDnDAction(int action) {
this.action = action;
// This if statement is a workaround for a KWin bug.
// KWin 6.5.1 may send an additional action(0) after dnd_drop_performed().
// Spec says that after dnd_drop_performed(), no further action() events will be sent,
// except for maybe action(dnd_ask), but since we do not announce support for dnd_ask,
// we don't need to worry about it.
if (!didSucceed) {
this.action = action;
}
}
@Override

View File

@@ -70,7 +70,7 @@ public class WLDropTargetContextPeer extends SunDropTargetContextPeer {
int dropAction = 0;
if (hasTarget() && event != MouseEvent.MOUSE_EXITED) {
dropAction = currentOffer.getSelectedAction();
dropAction = WLDataDevice.waylandActionsToJava(currentOffer.getSelectedAction());
}
postDropTargetEvent(
@@ -106,7 +106,10 @@ public class WLDropTargetContextPeer extends SunDropTargetContextPeer {
}
@Override
protected void doDropDone(boolean success, int dropAction, boolean isLocal) {
protected synchronized void doDropDone(boolean success, int dropAction, boolean isLocal) {
if (success && currentOffer != null) {
currentOffer.finishDnD();
}
reset();
}
@@ -115,17 +118,20 @@ public class WLDropTargetContextPeer extends SunDropTargetContextPeer {
return;
}
int actions = 0;
int javaActions = 0;
if (hasTarget()) {
actions = WLDataDevice.javaActionsToWayland(getTargetActions());
javaActions = getTargetActions();
}
int preferredAction = SunDragSourceContextPeer.convertModifiersToDropAction(WLToolkit.getInputState().getModifiers(), actions);
int javaPreferredAction = SunDragSourceContextPeer.convertModifiersToDropAction(WLToolkit.getInputState().getModifiers(), javaActions);
if (actions != lastActions || preferredAction != lastPreferredAction) {
currentOffer.setDnDActions(actions, preferredAction);
lastActions = actions;
lastPreferredAction = preferredAction;
int waylandActions = WLDataDevice.javaActionsToWayland(javaActions);
int waylandPreferredAction = WLDataDevice.javaActionsToWayland(javaPreferredAction);
if (waylandActions != lastActions || waylandPreferredAction != lastPreferredAction) {
currentOffer.setDnDActions(waylandActions, waylandPreferredAction);
lastActions = waylandActions;
lastPreferredAction = waylandPreferredAction;
}
}

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

@@ -43,6 +43,8 @@ import java.awt.event.InputEvent;
* @param pointerButtonPressedEvent null or the latest PointerButtonEvent such that getIsButtonPressed() == true
* @param modifiers a bit set of modifiers reflecting currently pressed keys (@see WLInputState.getNewModifiers())
* @param surfaceForKeyboardInput represents 'struct wl_surface*' that keyboards events should go to
* @param isPointerOverSurface true if the mouse pointer has entered a surface and has not left yet
* @param latestInputSerial the serial of the latest input event (key or pointer button press)
*/
record WLInputState(WLPointerEvent eventWithSurface,
long pointerEnterSerial,
@@ -54,7 +56,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
PointerButtonEvent pointerButtonPressedEvent,
int modifiers,
long surfaceForKeyboardInput,
boolean isPointerOverSurface) {
boolean isPointerOverSurface,
long latestInputSerial) {
/**
* Groups together information about a mouse pointer button event.
* @param surface 'struct wl_surface*' the button was pressed over
@@ -75,7 +78,7 @@ record WLInputState(WLPointerEvent eventWithSurface,
static WLInputState initialState() {
return new WLInputState(null, 0, 0, 0, 0, null, null,
null, 0, 0, false);
null, 0, 0, false, 0);
}
/**
@@ -101,6 +104,9 @@ record WLInputState(WLPointerEvent eventWithSurface,
boolean newPointerOverSurface = (pointerEvent.hasEnterEvent() || isPointerOverSurface)
&& !pointerEvent.hasLeaveEvent();
final long newLatestInputEventSerial = pointerEvent.hasButtonEvent()
? pointerEvent.getSerial() : latestInputSerial;
return new WLInputState(
newEventWithSurface,
newPointerEnterSerial,
@@ -112,7 +118,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
newPointerButtonEvent,
newModifiers,
surfaceForKeyboardInput,
newPointerOverSurface);
newPointerOverSurface,
newLatestInputEventSerial);
}
public WLInputState updatedFromKeyEvent(long serial) {
@@ -127,7 +134,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
modifiers,
surfaceForKeyboardInput,
isPointerOverSurface);
isPointerOverSurface,
serial);
}
public WLInputState updatedFromKeyboardEnterEvent(long serial, long surfacePtr) {
@@ -143,7 +151,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
modifiers,
surfacePtr,
isPointerOverSurface);
isPointerOverSurface,
latestInputSerial);
}
public WLInputState updatedFromKeyboardModifiersEvent(long serial, int keyboardModifiers) {
@@ -161,7 +170,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
newModifiers,
surfaceForKeyboardInput,
isPointerOverSurface);
isPointerOverSurface,
latestInputSerial);
}
public WLInputState updatedFromKeyboardLeaveEvent(long serial, long surfacePtr) {
@@ -185,7 +195,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
newModifiers,
0,
isPointerOverSurface);
isPointerOverSurface,
latestInputSerial);
}
public WLInputState updatedFromUnregisteredSurface(long surfacePtr) {
@@ -203,7 +214,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
modifiers,
0,
isPointerOverSurface);
isPointerOverSurface,
latestInputSerial);
} else {
return this;
}
@@ -221,7 +233,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
pointerButtonPressedEvent,
modifiers & ~WLPointerEvent.PointerButtonCodes.combinedMask(),
surfaceForKeyboardInput,
false);
false,
latestInputSerial);
}
private PointerButtonEvent getNewPointerButtonEvent(WLPointerEvent pointerEvent,

View File

@@ -83,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;
@@ -142,6 +143,11 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
private static final boolean isKDE;
// NOTE: xdg_toplevel_icon_v1 is pretty much only supported on KDE, and KWin always sends 96px as the icon size,
// regardless of the display resolution, scale, or anything else.
// TODO: this is currently unused
private static final java.util.List<Integer> preferredIconSizes = new ArrayList<>();
private static native void initIDs(long displayPtr);
static {
@@ -173,11 +179,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");
@@ -255,7 +281,9 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
WLToolkit.awtLock();
try {
dispatchEventsOnEDT();
dataDevice.performDeletionsOnEDT();
if (dataDevice != null) {
dataDevice.performDeletionsOnEDT();
}
} finally {
eventsQueued.release();
WLToolkit.awtUnlock();
@@ -1071,6 +1099,15 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
}
}
/**
* @return true if xdg-decoration-unstable-v1 is supported and false otherwise.
*/
public static boolean isSSDAvailable() {
return isSSDAvailableImpl();
}
private static native boolean isSSDAvailableImpl();
private native int readEvents();
private native void dispatchEventsOnEDT();
private native void flushImpl();
@@ -1109,4 +1146,9 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
public static boolean isKDE() {
return isKDE;
}
// called from native
private static void handleToplevelIconSize(int size) {
preferredIconSizes.add(size);
}
}

View File

@@ -39,7 +39,9 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
@@ -51,6 +53,7 @@ import java.awt.image.BufferedImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;
import java.lang.ref.WeakReference;
import java.util.List;
public class WLWindowPeer extends WLComponentPeer implements WindowPeer, SurfacePixelGrabber {
private static Font defaultFont;
@@ -77,7 +80,11 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
}
public WLWindowPeer(Window target) {
super(target);
this(target, true);
}
public WLWindowPeer(Window target, boolean dropShadow) {
super(target, dropShadow);
if (!target.isFontSet()) {
target.setFont(getDefaultFont());
@@ -176,7 +183,38 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
@Override
public void updateIconImages() {
// No support for this from Wayland, icon is a desktop integration feature.
List<Image> iconImages = getWindow().getIconImages();
if (iconImages == null || iconImages.isEmpty()) {
setIcon(0, null);
return;
}
Image image = iconImages.stream()
.filter(x -> x.getWidth(null) > 0 && x.getHeight(null) > 0)
.filter(x -> x.getWidth(null) == x.getHeight(null))
.max((a, b) -> Integer.compare(a.getWidth(null), b.getWidth(null)))
.orElse(null);
if (image == null) {
return;
}
int width = image.getWidth(null);
int height = image.getHeight(null);
int size = width;
BufferedImage bufferedImage;
if (image instanceof BufferedImage && ((BufferedImage) image).getType() == BufferedImage.TYPE_INT_ARGB) {
bufferedImage = (BufferedImage) image;
} else {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
}
int[] pixels = new int[width * height];
bufferedImage.getRGB(0, 0, width, height, pixels, 0, width);
setIcon(size, pixels);
}
@Override

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