elements(MemoryLayout elementLayout) {
return StreamSupport.stream(spliterator(elementLayout), false);
}
+ // FILL_NATIVE_THRESHOLD must be a power of two and should be greater than 2^3
+ // Update the value for Aarch64 once 8338975 is fixed.
+ private static final long FILL_NATIVE_THRESHOLD = 1L << (Architecture.isAARCH64() ? 10 : 5);
+
@Override
- public final MemorySegment fill(byte value){
- checkAccess(0, length, false);
- SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value);
+ @ForceInline
+ public final MemorySegment fill(byte value) {
+ checkReadOnly(false);
+ if (length == 0) {
+ // Implicit state check
+ checkValidState();
+ } else if (length < FILL_NATIVE_THRESHOLD) {
+ // 0 <= length < FILL_NATIVE_LIMIT : 0...0X...XXXX
+
+ // Handle smaller segments directly without transitioning to native code
+ final long u = Byte.toUnsignedLong(value);
+ final long longValue = u << 56 | u << 48 | u << 40 | u << 32 | u << 24 | u << 16 | u << 8 | u;
+
+ int offset = 0;
+ // 0...0X...X000
+ final int limit = (int) (length & (FILL_NATIVE_THRESHOLD - 8));
+ for (; offset < limit; offset += 8) {
+ SCOPED_MEMORY_ACCESS.putLong(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, longValue);
+ }
+ int remaining = (int) length - limit;
+ // 0...0X00
+ if (remaining >= 4) {
+ SCOPED_MEMORY_ACCESS.putInt(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, (int) longValue);
+ offset += 4;
+ remaining -= 4;
+ }
+ // 0...00X0
+ if (remaining >= 2) {
+ SCOPED_MEMORY_ACCESS.putShort(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, (short) longValue);
+ offset += 2;
+ remaining -= 2;
+ }
+ // 0...000X
+ if (remaining == 1) {
+ SCOPED_MEMORY_ACCESS.putByte(sessionImpl(), unsafeGetBase(), unsafeGetOffset() + offset, value);
+ }
+ // We have now fully handled 0...0X...XXXX
+ } else {
+ // Handle larger segments via native calls
+ SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value);
+ }
return this;
}
diff --git a/src/java.base/share/native/libjli/jli_util.h b/src/java.base/share/native/libjli/jli_util.h
index cacb0d65cb0f3..4bd72abc2db74 100644
--- a/src/java.base/share/native/libjli/jli_util.h
+++ b/src/java.base/share/native/libjli/jli_util.h
@@ -113,6 +113,9 @@ JLI_SetTraceLauncher();
jboolean JLI_IsTraceLauncher();
+// This is defined in link_type.c due to linking restraints
+jboolean JLI_IsStaticallyLinked();
+
/*
* JLI_List - a dynamic list of char*
*/
diff --git a/src/java.base/share/native/libjli/link_type.c b/src/java.base/share/native/libjli/link_type.c
new file mode 100644
index 0000000000000..aa060ddb00e29
--- /dev/null
+++ b/src/java.base/share/native/libjli/link_type.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+
+// This is in a separate file since it will need to be compiled to two different
+// object files, depending on if we are going to build a static or a dynamic
+// library.
+
+jboolean JLI_IsStaticallyLinked(void) {
+#ifdef STATIC_BUILD
+ return JNI_TRUE;
+#else
+ return JNI_FALSE;
+#endif
+}
diff --git a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
index 57d911e35de0a..acc7f0c73c903 100644
--- a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
+++ b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c
@@ -661,11 +661,8 @@ pid_t unix_getParentPidAndTimings(JNIEnv *env, pid_t pid,
void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
psinfo_t psinfo;
- char fn[32];
- char exePath[PATH_MAX];
char prargs[PRARGSZ + 1];
jstring cmdexe = NULL;
- int ret;
/*
* Now try to open /proc/%d/psinfo
diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c
index 988c4bd2646f9..bc55f099bd95a 100644
--- a/src/java.base/unix/native/libjava/TimeZone_md.c
+++ b/src/java.base/unix/native/libjava/TimeZone_md.c
@@ -41,8 +41,6 @@
#include "TimeZone_md.h"
#include "path_util.h"
-static char *isFileIdentical(char* buf, size_t size, char *pathname);
-
#define fileopen fopen
#define filegets fgets
#define fileclose fclose
@@ -59,11 +57,8 @@ static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
static const char popularZones[][4] = {"UTC", "GMT"};
-#if defined(_AIX)
-static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
-#endif
-
#if defined(__linux__) || defined(MACOSX)
+static char *isFileIdentical(char* buf, size_t size, char *pathname);
/*
* remove repeated path separators ('/') in the given 'path'.
@@ -356,6 +351,7 @@ getPlatformTimeZoneID()
}
#elif defined(_AIX)
+static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
static char *
getPlatformTimeZoneID()
diff --git a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c
index 4907200db72e8..908b7cca653cc 100644
--- a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c
+++ b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c
@@ -493,9 +493,6 @@ static StatusWindow *createStatusWindow(Window parent) {
XWindowAttributes xwa;
XWindowAttributes xxwa;
/* Variable for XCreateFontSet()*/
- char **mclr;
- int mccr = 0;
- char *dsr;
unsigned long bg, fg, light, dim;
int x, y, off_x, off_y, xx, yy;
unsigned int w, h, bw, depth;
diff --git a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c
index 216da01e0cd62..173d44d96c845 100644
--- a/src/java.desktop/unix/native/common/awt/CUPSfuncs.c
+++ b/src/java.desktop/unix/native/common/awt/CUPSfuncs.c
@@ -202,7 +202,6 @@ Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env,
cups_dest_t *dests;
char *defaultPrinter = NULL;
int num_dests = j2d_cupsGetDests(&dests);
- int i = 0;
cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests);
if (dest != NULL) {
defaultPrinter = dest->name;
diff --git a/src/java.desktop/unix/native/common/awt/X11Color.c b/src/java.desktop/unix/native/common/awt/X11Color.c
index 6d3f4e7b246e9..2d3fd48091489 100644
--- a/src/java.desktop/unix/native/common/awt/X11Color.c
+++ b/src/java.desktop/unix/native/common/awt/X11Color.c
@@ -338,7 +338,7 @@ awt_allocate_colors(AwtGraphicsConfigDataPtr awt_data)
unsigned char reds[256], greens[256], blues[256];
int indices[256];
Colormap cm;
- int i, j, k, cmapsize, nfree, depth, bpp;
+ int i, k, cmapsize, nfree, depth, bpp;
int allocatedColorsNum, unavailableColorsNum;
XPixmapFormatValues *pPFV;
int numpfv;
@@ -878,7 +878,6 @@ awt_allocate_colors(AwtGraphicsConfigDataPtr awt_data)
jobject getColorSpace(JNIEnv* env, jint csID) {
jclass clazz;
- jobject cspaceL;
jmethodID mid;
clazz = (*env)->FindClass(env,"java/awt/color/ColorSpace");
@@ -1033,7 +1032,6 @@ jobject awtJNI_GetColorModel(JNIEnv *env, AwtGraphicsConfigDataPtr aData)
jobject validBits = NULL;
ColorEntry *c;
int i, allocAllGray, b, allvalid, paletteSize;
- jlong pData;
if (aData->awt_visInfo.depth == 12) {
paletteSize = MAX_PALETTE12_SIZE;
@@ -1233,11 +1231,10 @@ jobject awtJNI_GetColorModel(JNIEnv *env, AwtGraphicsConfigDataPtr aData)
void
awt_allocate_systemrgbcolors (jint *rgbColors, int num_colors,
AwtGraphicsConfigDataPtr awtData) {
- int i, pixel;
- for (i = 0; i < num_colors; i++)
- pixel = alloc_col (awt_display, awtData->awt_cmap, red (rgbColors [i]),
- green (rgbColors [i]), blue (rgbColors [i]), -1,
- awtData);
+ for (int i = 0; i < num_colors; i++)
+ alloc_col (awt_display, awtData->awt_cmap, red (rgbColors [i]),
+ green (rgbColors [i]), blue (rgbColors [i]), -1,
+ awtData);
}
int
diff --git a/src/java.desktop/unix/native/common/awt/fontpath.c b/src/java.desktop/unix/native/common/awt/fontpath.c
index b270a3fc94d7f..2da0ec0328bee 100644
--- a/src/java.desktop/unix/native/common/awt/fontpath.c
+++ b/src/java.desktop/unix/native/common/awt/fontpath.c
@@ -100,7 +100,6 @@ typedef struct {
jboolean isDisplayLocal(JNIEnv *env) {
static jboolean isLocal = False;
static jboolean isLocalSet = False;
- jboolean ret;
if (! isLocalSet) {
jclass geCls = (*env)->FindClass(env, "java/awt/GraphicsEnvironment");
@@ -134,7 +133,7 @@ jboolean isDisplayLocal(JNIEnv *env) {
static char **getX11FontPath ()
{
char **x11Path, **fontdirs;
- int i, pos, slen, nPaths, numDirs;
+ int i, pos, slen, nPaths;
x11Path = XGetFontPath (awt_display, &nPaths);
@@ -533,7 +532,6 @@ static char **getFontConfigLocations() {
char **fontdirs;
int numdirs = 0;
- FcInitLoadConfigFuncType FcInitLoadConfig;
FcPatternBuildFuncType FcPatternBuild;
FcObjectSetFuncType FcObjectSetBuild;
FcFontListFuncType FcFontList;
@@ -543,14 +541,10 @@ static char **getFontConfigLocations() {
FcObjectSetDestroyFuncType FcObjectSetDestroy;
FcFontSetDestroyFuncType FcFontSetDestroy;
- FcConfig *fontconfig;
FcPattern *pattern;
FcObjectSet *objset;
FcFontSet *fontSet;
- FcStrList *strList;
- FcChar8 *str;
- int i, f, found, len=0;
- char **fontPath;
+ int i, f, found;
void* libfontconfig = openFontConfig();
diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c b/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c
index 2ab6f287b690f..521b7cfef3ab4 100644
--- a/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c
+++ b/src/java.desktop/unix/native/common/java2d/x11/X11FontScaler_md.c
@@ -43,8 +43,6 @@
static GC pixmapGC = 0;
static Pixmap pixmap = 0;
-static Atom psAtom = 0;
-static Atom fullNameAtom = 0;
static int pixmapWidth = 0;
static int pixmapHeight = 0;
@@ -127,9 +125,9 @@ JNIEXPORT int JNICALL AWTCountFonts(char* xlfd) {
}
JNIEXPORT void JNICALL AWTLoadFont(char* name, AWTFont *pReturn) {
- JNIEnv *env;
*pReturn = NULL;
#ifndef HEADLESS
+ JNIEnv *env;
FONT_AWT_LOCK();
*pReturn = (AWTFont)XLoadQueryFont(awt_display, name);
AWT_UNLOCK();
@@ -268,7 +266,7 @@ JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) {
XCharStruct xcs;
XImage *ximage;
int h, i, j, nbytes;
- unsigned char *srcRow, *dstRow, *dstByte;
+ unsigned char *srcRow, *dstRow;
int wholeByteCount, remainingBitsCount;
unsigned int imageSize;
JNIEnv *env;
diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c b/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c
index 871c129ca913d..216fe8090ff2e 100644
--- a/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c
+++ b/src/java.desktop/unix/native/common/java2d/x11/X11Renderer.c
@@ -571,7 +571,6 @@ Java_sun_java2d_x11_X11Renderer_XDoPath
#ifndef HEADLESS
X11SDOps *xsdo = (X11SDOps *) pXSData;
jarray typesArray;
- jobject pointArray;
jarray coordsArray;
jint numTypes;
jint fillRule;
diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c
index 36d6feb6029a7..e62ccff4653a2 100644
--- a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c
+++ b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c
@@ -882,11 +882,9 @@ static void X11SD_GetRasInfo(JNIEnv *env,
} else
#endif /* MITSHM */
if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) {
- int x, y, w, h;
+ int x, y;
x = pRasInfo->bounds.x1;
y = pRasInfo->bounds.y1;
- w = pRasInfo->bounds.x2 - x;
- h = pRasInfo->bounds.y2 - y;
xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags);
if (xpriv->img) {
diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c b/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c
index c7aff6f34c84f..d50ef00f94532 100644
--- a/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c
+++ b/src/java.desktop/unix/native/common/java2d/x11/X11TextRenderer_md.c
@@ -213,7 +213,7 @@ AWTDrawGlyphList(JNIEnv *env, jobject xtr,
XImage *theImage;
Pixmap thePixmap;
XGCValues xgcv;
- int scan, screen;
+ int screen;
AwtGraphicsConfigDataPtr cData;
X11SDOps *xsdo = (X11SDOps *)jlong_to_ptr(dstData);
jint cx1, cy1, cx2, cy2;
@@ -236,8 +236,6 @@ AWTDrawGlyphList(JNIEnv *env, jobject xtr,
thePixmap = cData->monoPixmap;
theGC = cData->monoPixmapGC;
- scan = theImage->bytes_per_line;
-
xgcv.fill_style = FillStippled;
xgcv.stipple = thePixmap;
xgcv.ts_x_origin = bounds->x1;
diff --git a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
index b2dedca351c5f..389e25caaec0c 100644
--- a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
+++ b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -116,44 +116,41 @@ AWT_OnLoad(JavaVM *vm, void *reserved)
}
jvm = vm;
-#ifndef STATIC_BUILD
- /* Get address of this library and the directory containing it. */
- dladdr((void *)AWT_OnLoad, &dlinfo);
- realpath((char *)dlinfo.dli_fname, buf);
- len = strlen(buf);
- p = strrchr(buf, '/');
-#endif
+
/*
* The code below is responsible for
* loading appropriate awt library, i.e. libawt_xawt or libawt_headless
*/
#ifdef MACOSX
- tk = LWAWT_PATH;
+ tk = LWAWT_PATH;
#else
- tk = XAWT_PATH;
-#endif
+ tk = XAWT_PATH;
-#ifndef MACOSX
if (AWTIsHeadless()) {
tk = HEADLESS_PATH;
}
#endif
-#ifndef STATIC_BUILD
- /* Calculate library name to load */
- strncpy(p, tk, MAXPATHLEN-len-1);
-#endif
+ if (!JVM_IsStaticallyLinked()) {
+ /* Get address of this library and the directory containing it. */
+ dladdr((void *)AWT_OnLoad, &dlinfo);
+ realpath((char *)dlinfo.dli_fname, buf);
+ len = strlen(buf);
+ p = strrchr(buf, '/');
-#ifndef STATIC_BUILD
- jstring jbuf = JNU_NewStringPlatform(env, buf);
- CHECK_EXCEPTION_FATAL(env, "Could not allocate library name");
- JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load",
- "(Ljava/lang/String;)V",
- jbuf);
+ /* Calculate library name to load */
+ strncpy(p, tk, MAXPATHLEN-len-1);
+
+ jstring jbuf = JNU_NewStringPlatform(env, buf);
+ CHECK_EXCEPTION_FATAL(env, "Could not allocate library name");
+ JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load",
+ "(Ljava/lang/String;)V",
+ jbuf);
+
+ awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
+ }
- awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
-#endif
return JNI_VERSION_1_2;
}
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
index aa2e88940dcae..33d2aeb66bbc1 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
@@ -304,7 +304,6 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
AwtGraphicsConfigDataPtr *graphicsConfigs;
AwtGraphicsConfigDataPtr defaultConfig;
int ind;
- char errmsg[128];
int xinawareScreen;
void* xrenderLibHandle = NULL;
XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL;
@@ -722,7 +721,6 @@ awt_init_Display(JNIEnv *env, jobject this)
jclass klass;
Display *dpy;
char errmsg[128];
- int i;
if (awt_display) {
return awt_display;
@@ -872,7 +870,6 @@ extern int mitShmPermissionMask;
void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
XShmSegmentInfo shminfo;
int XShmMajor, XShmMinor;
- int a, b, c;
AWT_LOCK();
if (canUseShmExt != UNSET_MITSHM) {
@@ -1154,7 +1151,7 @@ JNIEnv *env, jobject this, jint visualNum, jint screen)
AwtGraphicsConfigData *adata = NULL;
AwtScreenData asd = x11Screens[screen];
- int i, n;
+ int i;
int depth;
XImage * tempImage;
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c
index e2e3cd1180948..93c1f4d0c1a3f 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c
@@ -793,8 +793,6 @@ static list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,
XRectangle clip;
int image_only;
- int count=0 ;
-
*hasNonDefault = False;
XUnionRectWithRegion( bbox, bbox_region, bbox_region);
XGetWindowAttributes( disp, win, &win_attrs);
@@ -823,8 +821,6 @@ static list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,
malloc( sizeof( image_region_type)))) {
return (list_ptr) NULL;
}
- count++;
-
new_reg->visible_region = XCreateRegion();
new_reg->win = base_src->win;
new_reg->vis = base_src->vis;
diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
index e990cd9014a04..5a008d10a482c 100644
--- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
+++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
@@ -209,7 +209,7 @@ FreeColors(Display * display, Screen * screen, int numColors,
}
static void SplashCenter(Splash * splash) {
- Atom type, atom, actual_type;
+ Atom atom, actual_type;
int status, actual_format;
unsigned long nitems, bytes_after;
CARD16 *prop = NULL;
@@ -251,8 +251,6 @@ static void SplashUpdateSizeHints(Splash * splash) {
void
SplashCreateWindow(Splash * splash) {
- XSizeHints sizeHints;
-
XSetWindowAttributes attr;
attr.backing_store = NotUseful;
@@ -740,11 +738,10 @@ void
SplashCreateThread(Splash * splash) {
pthread_t thr;
pthread_attr_t attr;
- int rc;
int rslt = pthread_attr_init(&attr);
if (rslt != 0) return;
- rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash);
+ pthread_create(&thr, &attr, SplashScreenThread, (void *) splash);
pthread_attr_destroy(&attr);
}
diff --git a/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/src/java.management/share/classes/java/lang/management/ManagementFactory.java
index b1ac1d0391e54..a95102cd1258b 100644
--- a/src/java.management/share/classes/java/lang/management/ManagementFactory.java
+++ b/src/java.management/share/classes/java/lang/management/ManagementFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -95,7 +95,6 @@
*
* An application can access a platform MXBean in the following ways:
*
1. Direct access to an MXBean interface
- *
*
* - Get an MXBean instance by calling the
* {@link #getPlatformMXBean(Class) getPlatformMXBean} or
@@ -130,7 +129,6 @@
* for details.
*
*
- *
*
*
* The {@link #getPlatformManagementInterfaces getPlatformManagementInterfaces}
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java
deleted file mode 100644
index 8a076ca67cb6b..0000000000000
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/NaiveHuffman.java
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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 jdk.internal.net.http.hpack;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import static java.lang.String.format;
-
-/**
- * Huffman coding table.
- *
- *
Instances of this class are safe for use by multiple threads.
- *
- * @since 9
- */
-public final class NaiveHuffman {
-
- // TODO: check if reset is done in both reader and writer
-
- static final class Reader implements Huffman.Reader {
-
- private Node curr; // position in the trie
- private int len; // length of the path from the root to 'curr'
- private int p; // byte probe
-
- {
- reset();
- }
-
- @Override
- public void read(ByteBuffer source,
- Appendable destination,
- boolean isLast) throws IOException {
- read(source, destination, true, isLast);
- }
-
- // Takes 'isLast' rather than returns whether the reading is done or
- // not, for more informative exceptions.
- void read(ByteBuffer source,
- Appendable destination,
- boolean reportEOS, /* reportEOS is exposed for tests */
- boolean isLast) throws IOException {
- Node c = curr;
- int l = len;
- /*
- Since ByteBuffer is itself stateful, its position is
- remembered here NOT as a part of Reader's state,
- but to set it back in the case of a failure
- */
- int pos = source.position();
-
- while (source.hasRemaining()) {
- int d = source.get();
- for (; p != 0; p >>= 1) {
- c = c.getChild(p & d);
- l++;
- if (c.isLeaf()) {
- if (reportEOS && c.isEOSPath) {
- throw new IOException("Encountered EOS");
- }
- char ch;
- try {
- ch = c.getChar();
- } catch (IllegalStateException e) {
- source.position(pos); // do we need this?
- throw new IOException(e);
- }
- try {
- destination.append(ch);
- } catch (IOException e) {
- source.position(pos); // do we need this?
- throw e;
- }
- c = INSTANCE.root;
- l = 0;
- }
- curr = c;
- len = l;
- }
- resetProbe();
- pos++;
- }
- if (!isLast) {
- return; // it's too early to jump to any conclusions, let's wait
- }
- if (c.isLeaf()) {
- return; // it's perfectly ok, no extra padding bits
- }
- if (c.isEOSPath && len <= 7) {
- return; // it's ok, some extra padding bits
- }
- if (c.isEOSPath) {
- throw new IOException(
- "Padding is too long (len=" + len + ") " +
- "or unexpected end of data");
- }
- throw new IOException(
- "Not a EOS prefix padding or unexpected end of data");
- }
-
- @Override
- public void reset() {
- curr = INSTANCE.root;
- len = 0;
- resetProbe();
- }
-
- private void resetProbe() {
- p = 0x80;
- }
- }
-
- static final class Writer implements Huffman.Writer {
-
- private int pos; // position in 'source'
- private int avail = 8; // number of least significant bits available in 'curr'
- private int curr; // next byte to put to the destination
- private int rem; // number of least significant bits in 'code' yet to be processed
- private int code; // current code being written
-
- private CharSequence source;
- private int end;
-
- @Override
- public Writer from(CharSequence input, int start, int end) {
- if (start < 0 || end < 0 || end > input.length() || start > end) {
- throw new IndexOutOfBoundsException(
- String.format("input.length()=%s, start=%s, end=%s",
- input.length(), start, end));
- }
- pos = start;
- this.end = end;
- this.source = input;
- return this;
- }
-
- @Override
- public boolean write(ByteBuffer destination) {
- for (; pos < end; pos++) {
- if (rem == 0) {
- Code desc = INSTANCE.codeOf(source.charAt(pos));
- rem = desc.length;
- code = desc.code;
- }
- while (rem > 0) {
- if (rem < avail) {
- curr |= (code << (avail - rem));
- avail -= rem;
- rem = 0;
- } else {
- int c = (curr | (code >>> (rem - avail)));
- if (destination.hasRemaining()) {
- destination.put((byte) c);
- } else {
- return false;
- }
- curr = c;
- code <<= (32 - rem + avail); // throw written bits off the cliff (is this Sparta?)
- code >>>= (32 - rem + avail); // return to the position
- rem -= avail;
- curr = 0;
- avail = 8;
- }
- }
- }
-
- if (avail < 8) { // have to pad
- if (destination.hasRemaining()) {
- destination.put((byte) (curr | (INSTANCE.EOS.code >>> (INSTANCE.EOS.length - avail))));
- avail = 8;
- } else {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public Writer reset() {
- source = null;
- end = -1;
- pos = -1;
- avail = 8;
- curr = 0;
- code = 0;
- return this;
- }
-
- @Override
- public int lengthOf(CharSequence value, int start, int end) {
- return INSTANCE.lengthOf(value, start, end);
- }
- }
-
- /**
- * Shared instance.
- */
- public static final NaiveHuffman INSTANCE = new NaiveHuffman();
-
- private final Code EOS = new Code(0x3fffffff, 30);
- private final Code[] codes = new Code[257];
- private final Node root = new Node() {
- @Override
- public String toString() { return "root"; }
- };
-
- // TODO: consider builder and immutable trie
- private NaiveHuffman() {
- // @formatter:off
- addChar(0, 0x1ff8, 13);
- addChar(1, 0x7fffd8, 23);
- addChar(2, 0xfffffe2, 28);
- addChar(3, 0xfffffe3, 28);
- addChar(4, 0xfffffe4, 28);
- addChar(5, 0xfffffe5, 28);
- addChar(6, 0xfffffe6, 28);
- addChar(7, 0xfffffe7, 28);
- addChar(8, 0xfffffe8, 28);
- addChar(9, 0xffffea, 24);
- addChar(10, 0x3ffffffc, 30);
- addChar(11, 0xfffffe9, 28);
- addChar(12, 0xfffffea, 28);
- addChar(13, 0x3ffffffd, 30);
- addChar(14, 0xfffffeb, 28);
- addChar(15, 0xfffffec, 28);
- addChar(16, 0xfffffed, 28);
- addChar(17, 0xfffffee, 28);
- addChar(18, 0xfffffef, 28);
- addChar(19, 0xffffff0, 28);
- addChar(20, 0xffffff1, 28);
- addChar(21, 0xffffff2, 28);
- addChar(22, 0x3ffffffe, 30);
- addChar(23, 0xffffff3, 28);
- addChar(24, 0xffffff4, 28);
- addChar(25, 0xffffff5, 28);
- addChar(26, 0xffffff6, 28);
- addChar(27, 0xffffff7, 28);
- addChar(28, 0xffffff8, 28);
- addChar(29, 0xffffff9, 28);
- addChar(30, 0xffffffa, 28);
- addChar(31, 0xffffffb, 28);
- addChar(32, 0x14, 6);
- addChar(33, 0x3f8, 10);
- addChar(34, 0x3f9, 10);
- addChar(35, 0xffa, 12);
- addChar(36, 0x1ff9, 13);
- addChar(37, 0x15, 6);
- addChar(38, 0xf8, 8);
- addChar(39, 0x7fa, 11);
- addChar(40, 0x3fa, 10);
- addChar(41, 0x3fb, 10);
- addChar(42, 0xf9, 8);
- addChar(43, 0x7fb, 11);
- addChar(44, 0xfa, 8);
- addChar(45, 0x16, 6);
- addChar(46, 0x17, 6);
- addChar(47, 0x18, 6);
- addChar(48, 0x0, 5);
- addChar(49, 0x1, 5);
- addChar(50, 0x2, 5);
- addChar(51, 0x19, 6);
- addChar(52, 0x1a, 6);
- addChar(53, 0x1b, 6);
- addChar(54, 0x1c, 6);
- addChar(55, 0x1d, 6);
- addChar(56, 0x1e, 6);
- addChar(57, 0x1f, 6);
- addChar(58, 0x5c, 7);
- addChar(59, 0xfb, 8);
- addChar(60, 0x7ffc, 15);
- addChar(61, 0x20, 6);
- addChar(62, 0xffb, 12);
- addChar(63, 0x3fc, 10);
- addChar(64, 0x1ffa, 13);
- addChar(65, 0x21, 6);
- addChar(66, 0x5d, 7);
- addChar(67, 0x5e, 7);
- addChar(68, 0x5f, 7);
- addChar(69, 0x60, 7);
- addChar(70, 0x61, 7);
- addChar(71, 0x62, 7);
- addChar(72, 0x63, 7);
- addChar(73, 0x64, 7);
- addChar(74, 0x65, 7);
- addChar(75, 0x66, 7);
- addChar(76, 0x67, 7);
- addChar(77, 0x68, 7);
- addChar(78, 0x69, 7);
- addChar(79, 0x6a, 7);
- addChar(80, 0x6b, 7);
- addChar(81, 0x6c, 7);
- addChar(82, 0x6d, 7);
- addChar(83, 0x6e, 7);
- addChar(84, 0x6f, 7);
- addChar(85, 0x70, 7);
- addChar(86, 0x71, 7);
- addChar(87, 0x72, 7);
- addChar(88, 0xfc, 8);
- addChar(89, 0x73, 7);
- addChar(90, 0xfd, 8);
- addChar(91, 0x1ffb, 13);
- addChar(92, 0x7fff0, 19);
- addChar(93, 0x1ffc, 13);
- addChar(94, 0x3ffc, 14);
- addChar(95, 0x22, 6);
- addChar(96, 0x7ffd, 15);
- addChar(97, 0x3, 5);
- addChar(98, 0x23, 6);
- addChar(99, 0x4, 5);
- addChar(100, 0x24, 6);
- addChar(101, 0x5, 5);
- addChar(102, 0x25, 6);
- addChar(103, 0x26, 6);
- addChar(104, 0x27, 6);
- addChar(105, 0x6, 5);
- addChar(106, 0x74, 7);
- addChar(107, 0x75, 7);
- addChar(108, 0x28, 6);
- addChar(109, 0x29, 6);
- addChar(110, 0x2a, 6);
- addChar(111, 0x7, 5);
- addChar(112, 0x2b, 6);
- addChar(113, 0x76, 7);
- addChar(114, 0x2c, 6);
- addChar(115, 0x8, 5);
- addChar(116, 0x9, 5);
- addChar(117, 0x2d, 6);
- addChar(118, 0x77, 7);
- addChar(119, 0x78, 7);
- addChar(120, 0x79, 7);
- addChar(121, 0x7a, 7);
- addChar(122, 0x7b, 7);
- addChar(123, 0x7ffe, 15);
- addChar(124, 0x7fc, 11);
- addChar(125, 0x3ffd, 14);
- addChar(126, 0x1ffd, 13);
- addChar(127, 0xffffffc, 28);
- addChar(128, 0xfffe6, 20);
- addChar(129, 0x3fffd2, 22);
- addChar(130, 0xfffe7, 20);
- addChar(131, 0xfffe8, 20);
- addChar(132, 0x3fffd3, 22);
- addChar(133, 0x3fffd4, 22);
- addChar(134, 0x3fffd5, 22);
- addChar(135, 0x7fffd9, 23);
- addChar(136, 0x3fffd6, 22);
- addChar(137, 0x7fffda, 23);
- addChar(138, 0x7fffdb, 23);
- addChar(139, 0x7fffdc, 23);
- addChar(140, 0x7fffdd, 23);
- addChar(141, 0x7fffde, 23);
- addChar(142, 0xffffeb, 24);
- addChar(143, 0x7fffdf, 23);
- addChar(144, 0xffffec, 24);
- addChar(145, 0xffffed, 24);
- addChar(146, 0x3fffd7, 22);
- addChar(147, 0x7fffe0, 23);
- addChar(148, 0xffffee, 24);
- addChar(149, 0x7fffe1, 23);
- addChar(150, 0x7fffe2, 23);
- addChar(151, 0x7fffe3, 23);
- addChar(152, 0x7fffe4, 23);
- addChar(153, 0x1fffdc, 21);
- addChar(154, 0x3fffd8, 22);
- addChar(155, 0x7fffe5, 23);
- addChar(156, 0x3fffd9, 22);
- addChar(157, 0x7fffe6, 23);
- addChar(158, 0x7fffe7, 23);
- addChar(159, 0xffffef, 24);
- addChar(160, 0x3fffda, 22);
- addChar(161, 0x1fffdd, 21);
- addChar(162, 0xfffe9, 20);
- addChar(163, 0x3fffdb, 22);
- addChar(164, 0x3fffdc, 22);
- addChar(165, 0x7fffe8, 23);
- addChar(166, 0x7fffe9, 23);
- addChar(167, 0x1fffde, 21);
- addChar(168, 0x7fffea, 23);
- addChar(169, 0x3fffdd, 22);
- addChar(170, 0x3fffde, 22);
- addChar(171, 0xfffff0, 24);
- addChar(172, 0x1fffdf, 21);
- addChar(173, 0x3fffdf, 22);
- addChar(174, 0x7fffeb, 23);
- addChar(175, 0x7fffec, 23);
- addChar(176, 0x1fffe0, 21);
- addChar(177, 0x1fffe1, 21);
- addChar(178, 0x3fffe0, 22);
- addChar(179, 0x1fffe2, 21);
- addChar(180, 0x7fffed, 23);
- addChar(181, 0x3fffe1, 22);
- addChar(182, 0x7fffee, 23);
- addChar(183, 0x7fffef, 23);
- addChar(184, 0xfffea, 20);
- addChar(185, 0x3fffe2, 22);
- addChar(186, 0x3fffe3, 22);
- addChar(187, 0x3fffe4, 22);
- addChar(188, 0x7ffff0, 23);
- addChar(189, 0x3fffe5, 22);
- addChar(190, 0x3fffe6, 22);
- addChar(191, 0x7ffff1, 23);
- addChar(192, 0x3ffffe0, 26);
- addChar(193, 0x3ffffe1, 26);
- addChar(194, 0xfffeb, 20);
- addChar(195, 0x7fff1, 19);
- addChar(196, 0x3fffe7, 22);
- addChar(197, 0x7ffff2, 23);
- addChar(198, 0x3fffe8, 22);
- addChar(199, 0x1ffffec, 25);
- addChar(200, 0x3ffffe2, 26);
- addChar(201, 0x3ffffe3, 26);
- addChar(202, 0x3ffffe4, 26);
- addChar(203, 0x7ffffde, 27);
- addChar(204, 0x7ffffdf, 27);
- addChar(205, 0x3ffffe5, 26);
- addChar(206, 0xfffff1, 24);
- addChar(207, 0x1ffffed, 25);
- addChar(208, 0x7fff2, 19);
- addChar(209, 0x1fffe3, 21);
- addChar(210, 0x3ffffe6, 26);
- addChar(211, 0x7ffffe0, 27);
- addChar(212, 0x7ffffe1, 27);
- addChar(213, 0x3ffffe7, 26);
- addChar(214, 0x7ffffe2, 27);
- addChar(215, 0xfffff2, 24);
- addChar(216, 0x1fffe4, 21);
- addChar(217, 0x1fffe5, 21);
- addChar(218, 0x3ffffe8, 26);
- addChar(219, 0x3ffffe9, 26);
- addChar(220, 0xffffffd, 28);
- addChar(221, 0x7ffffe3, 27);
- addChar(222, 0x7ffffe4, 27);
- addChar(223, 0x7ffffe5, 27);
- addChar(224, 0xfffec, 20);
- addChar(225, 0xfffff3, 24);
- addChar(226, 0xfffed, 20);
- addChar(227, 0x1fffe6, 21);
- addChar(228, 0x3fffe9, 22);
- addChar(229, 0x1fffe7, 21);
- addChar(230, 0x1fffe8, 21);
- addChar(231, 0x7ffff3, 23);
- addChar(232, 0x3fffea, 22);
- addChar(233, 0x3fffeb, 22);
- addChar(234, 0x1ffffee, 25);
- addChar(235, 0x1ffffef, 25);
- addChar(236, 0xfffff4, 24);
- addChar(237, 0xfffff5, 24);
- addChar(238, 0x3ffffea, 26);
- addChar(239, 0x7ffff4, 23);
- addChar(240, 0x3ffffeb, 26);
- addChar(241, 0x7ffffe6, 27);
- addChar(242, 0x3ffffec, 26);
- addChar(243, 0x3ffffed, 26);
- addChar(244, 0x7ffffe7, 27);
- addChar(245, 0x7ffffe8, 27);
- addChar(246, 0x7ffffe9, 27);
- addChar(247, 0x7ffffea, 27);
- addChar(248, 0x7ffffeb, 27);
- addChar(249, 0xffffffe, 28);
- addChar(250, 0x7ffffec, 27);
- addChar(251, 0x7ffffed, 27);
- addChar(252, 0x7ffffee, 27);
- addChar(253, 0x7ffffef, 27);
- addChar(254, 0x7fffff0, 27);
- addChar(255, 0x3ffffee, 26);
- addEOS (256, EOS.code, EOS.length);
- // @formatter:on
- }
-
-
- /**
- * Calculates the number of bytes required to represent the given {@code
- * CharSequence} with the Huffman coding.
- *
- * @param value
- * characters
- *
- * @return number of bytes
- *
- * @throws NullPointerException
- * if the value is null
- */
- public int lengthOf(CharSequence value) {
- return lengthOf(value, 0, value.length());
- }
-
- /**
- * Calculates the number of bytes required to represent a subsequence of the
- * given {@code CharSequence} with the Huffman coding.
- *
- * @param value
- * characters
- * @param start
- * the start index, inclusive
- * @param end
- * the end index, exclusive
- *
- * @return number of bytes
- *
- * @throws NullPointerException
- * if the value is null
- * @throws IndexOutOfBoundsException
- * if any invocation of {@code value.charAt(i)}, where
- * {@code start <= i < end} would throw an IndexOutOfBoundsException
- */
- public int lengthOf(CharSequence value, int start, int end) {
- int len = 0;
- for (int i = start; i < end; i++) {
- char c = value.charAt(i);
- len += INSTANCE.codeOf(c).length;
- }
- // Integer division with ceiling, assumption:
- assert (len / 8 + (len % 8 != 0 ? 1 : 0)) == (len + 7) / 8 : len;
- return (len + 7) / 8;
- }
-
- private void addChar(int c, int code, int bitLength) {
- addLeaf(c, code, bitLength, false);
- codes[c] = new Code(code, bitLength);
- }
-
- private void addEOS(int c, int code, int bitLength) {
- addLeaf(c, code, bitLength, true);
- codes[c] = new Code(code, bitLength);
- }
-
- private void addLeaf(int c, int code, int bitLength, boolean isEOS) {
- if (bitLength < 1) {
- throw new IllegalArgumentException("bitLength < 1");
- }
- Node curr = root;
- for (int p = 1 << bitLength - 1; p != 0 && !curr.isLeaf(); p = p >> 1) {
- curr.isEOSPath |= isEOS; // If it's already true, it can't become false
- curr = curr.addChildIfAbsent(p & code);
- }
- curr.isEOSPath |= isEOS; // The last one needs to have this property as well
- if (curr.isLeaf()) {
- throw new IllegalStateException("Specified code is already taken");
- }
- curr.setChar((char) c);
- }
-
- private Code codeOf(char c) {
- if (c > 255) {
- throw new IllegalArgumentException("char=" + ((int) c));
- }
- return codes[c];
- }
-
- //
- // For debugging/testing purposes
- //
- Node getRoot() {
- return root;
- }
-
- //
- // Guarantees:
- //
- // if (isLeaf() == true) => getChar() is a legal call
- // if (isLeaf() == false) => getChild(i) is a legal call (though it can
- // return null)
- //
- static class Node {
-
- Node left;
- Node right;
- boolean isEOSPath;
-
- boolean charIsSet;
- char c;
-
- Node getChild(int selector) {
- if (isLeaf()) {
- throw new IllegalStateException("This is a leaf node");
- }
- Node result = selector == 0 ? left : right;
- if (result == null) {
- throw new IllegalStateException(format(
- "Node doesn't have a child (selector=%s)", selector));
- }
- return result;
- }
-
- boolean isLeaf() {
- return charIsSet;
- }
-
- char getChar() {
- if (!isLeaf()) {
- throw new IllegalStateException("This node is not a leaf node");
- }
- return c;
- }
-
- void setChar(char c) {
- if (charIsSet) {
- throw new IllegalStateException(
- "This node has been taken already");
- }
- if (left != null || right != null) {
- throw new IllegalStateException("The node cannot be made "
- + "a leaf as it's already has a child");
- }
- this.c = c;
- charIsSet = true;
- }
-
- Node addChildIfAbsent(int i) {
- if (charIsSet) {
- throw new IllegalStateException("The node cannot have a child "
- + "as it's already a leaf node");
- }
- Node child;
- if (i == 0) {
- if ((child = left) == null) {
- child = left = new Node();
- }
- } else {
- if ((child = right) == null) {
- child = right = new Node();
- }
- }
- return child;
- }
-
- @Override
- public String toString() {
- if (isLeaf()) {
- if (isEOSPath) {
- return "EOS";
- } else {
- return format("char: (%3s) '%s'", (int) c, c);
- }
- }
- return "/\\";
- }
- }
-
- // TODO: value-based class?
- // FIXME: can we re-use Node instead of this class?
- private static final class Code {
-
- final int code;
- final int length;
-
- private Code(int code, int length) {
- this.code = code;
- this.length = length;
- }
-
- public int getCode() {
- return code;
- }
-
- public int getLength() {
- return length;
- }
-
- @Override
- public String toString() {
- long p = 1 << length;
- return Long.toBinaryString(code + p).substring(1)
- + ", length=" + length;
- }
- }
-}
diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
index bebf8d0f05ae9..962b1ae51722b 100644
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -319,7 +319,7 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at
CHECK_EXCEPTION;
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
- THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file. For more information, export LIBSAPROC_DEBUG=1 and try again.");
}
env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
fillThreadsAndLoadObjects(env, this_obj, ph);
diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
index 4d1f57a018c28..79912a9b4dbbd 100644
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -1146,7 +1146,7 @@ static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle*
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
- THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
+ THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file. For more information, export LIBSAPROC_DEBUG=1 and try again.");
}
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
diff --git a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
index fef9ea965520d..5c7773809dae0 100644
--- a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
+++ b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -399,8 +399,11 @@ static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
IDebugSymbols* ptrIDebugSymbols = (IDebugSymbols*)env->GetLongField(obj, ptrIDebugSymbols_ID);
CHECK_EXCEPTION_(false);
- ptrIDebugSymbols->SetImagePath(imagePath);
- ptrIDebugSymbols->SetSymbolPath(symbolPath);
+ COM_VERIFY_OK_(ptrIDebugSymbols->SetImagePath(imagePath),
+ "Windbg Error: SetImagePath failed!", false);
+ COM_VERIFY_OK_(ptrIDebugSymbols->SetSymbolPath(symbolPath),
+ "Windbg Error: SetSymbolPath failed!", false);
+
return true;
}
@@ -829,6 +832,8 @@ JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLoc
return res;
}
+#define SYMBOL_BUFSIZE 512
+
/*
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
* Method: lookupByName0
@@ -852,10 +857,22 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
if (ptrIDebugSymbols->GetOffsetByName(name, &offset) != S_OK) {
return (jlong) 0;
}
+
+ // See JDK-8311993: WinDbg intermittently returns offset of "module!class::`vftable'" symbol
+ // when requested for decorated "class" or "class*" (i.e. "??_7class@@6B@"/"??_7class*@@6B@").
+ // As a workaround check if returned symbol contains requested symbol.
+ ULONG64 disp = 0L;
+ char buf[SYMBOL_BUFSIZE];
+ memset(buf, 0, sizeof(buf));
+ if (ptrIDebugSymbols->GetNameByOffset(offset, buf, sizeof(buf), 0, &disp) == S_OK) {
+ if (strstr(buf, name) == nullptr) {
+ return (jlong)0;
+ }
+ }
+
return (jlong) offset;
}
-#define SYMBOL_BUFSIZE 512
/*
* Class: sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal
* Method: lookupByAddress0
diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c b/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c
index d993bbc19955e..a06ed23dc035b 100644
--- a/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugLoop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -87,7 +87,9 @@ debugLoop_run(void)
/* Initialize all statics */
/* We may be starting a new connection after an error */
cmdQueue = NULL;
- cmdQueueLock = debugMonitorCreate("JDWP Command Queue Lock");
+ if (cmdQueueLock == NULL) {
+ cmdQueueLock = debugMonitorCreate("JDWP Command Queue Lock");
+ }
transportError = JNI_FALSE;
shouldListen = JNI_TRUE;
@@ -190,7 +192,6 @@ debugLoop_run(void)
* be trying to send.
*/
transport_close();
- debugMonitorDestroy(cmdQueueLock);
/* Reset for a new connection to this VM if it's still alive */
if ( ! gdata->vmDead ) {
diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/transport.c b/src/jdk.jdwp.agent/share/native/libjdwp/transport.c
index 273bb7ad9c148..f67e9da47ea94 100644
--- a/src/jdk.jdwp.agent/share/native/libjdwp/transport.c
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/transport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -23,6 +23,7 @@
* questions.
*/
+#include "jvm.h"
#include "util.h"
#include "utf_util.h"
#include "transport.h"
@@ -121,7 +122,11 @@ static void *
loadTransportLibrary(const char *libdir, const char *name)
{
char buf[MAXPATHLEN*2+100];
-#ifndef STATIC_BUILD
+
+ if (JVM_IsStaticallyLinked()) {
+ return (dbgsysLoadLibrary(NULL, buf, sizeof(buf)));
+ }
+
void *handle;
char libname[MAXPATHLEN+2];
const char *plibdir;
@@ -145,9 +150,6 @@ loadTransportLibrary(const char *libdir, const char *name)
/* dlopen (unix) / LoadLibrary (windows) the transport library */
handle = dbgsysLoadLibrary(libname, buf, sizeof(buf));
return handle;
-#else
- return (dbgsysLoadLibrary(NULL, buf, sizeof(buf)));
-#endif
}
/*
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
index 5521336f93859..71dc97d114e2c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
@@ -562,7 +562,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) {
// write begin event
getEventConfiguration(blockCodeBuilder);
// stack: [EW], [EW], [EventConfiguration]
- blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId);
+ blockCodeBuilder.loadConstant(eventTypeId);
// stack: [EW], [EW], [EventConfiguration] [long]
invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method());
// stack: [EW], [integer]
@@ -676,7 +676,7 @@ void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end, Label ex
// stack: [EW] [EW]
getEventConfiguration(blockCodeBuilder);
// stack: [EW] [EW] [EC]
- blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId);
+ blockCodeBuilder.loadConstant(eventTypeId);
invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method());
// stack: [EW] [int]
blockCodeBuilder.ifeq(excluded);
diff --git a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java
index b1d86a743a5c3..cb8b3bdf0a620 100644
--- a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java
+++ b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java
@@ -47,6 +47,8 @@
* {@code null} unless it's stated otherwise.
*
* @see java.lang.management.ManagementFactory#getPlatformMXBeans(Class)
+ *
+ * @since 1.6
*/
public interface HotSpotDiagnosticMXBean extends PlatformManagedObject {
/**
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 664ba0175a2ec..1b139063b5d66 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -53,6 +53,7 @@ compiler/loopopts/TestUnreachableInnerLoop.java 8288981 linux-s390x
compiler/c2/Test8004741.java 8235801 generic-all
compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
+compiler/c2/irTests/TestIfMinMax.java 8339220 linux-s390x
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
compiler/codecache/CheckLargePages.java 8332654 linux-x64
@@ -73,8 +74,6 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInf
compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586
compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586
-compiler/startup/StartupOutput.java 8326615 generic-x64
-
compiler/codecache/CodeCacheFullCountTest.java 8332954 generic-all
compiler/interpreter/Test6833129.java 8335266 generic-i586
diff --git a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java
index 0c4fb5a66ae93..d0b45333fb8b3 100644
--- a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java
+++ b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -187,8 +187,17 @@ public static void main(String[] args) throws Exception {
// Fails if not enough space for VM internal code
long minUseSpace = WHITE_BOX.getUintxVMFlag("CodeCacheMinimumUseSpace");
- // minimum size: CodeCacheMinimumUseSpace DEBUG_ONLY(* 3)
- long minSize = (Platform.isDebugBuild() ? 3 : 1) * minUseSpace;
+ long nMethodSizeLimit = WHITE_BOX.getIntxVMFlag("NMethodSizeLimit");
+ long codeEntryAlignment = WHITE_BOX.getIntxVMFlag("CodeEntryAlignment");
+ long c1MinCodeCacheSize = 11 * nMethodSizeLimit / 10;
+ long c2MinCodeCacheSize = 2048 /* PhaseOutput::MAX_inst_size */ +
+ 128 /* PhaseOutput::MAX_stubs_size */ +
+ 4 * 1024 /* initial_const_capacity */ +
+ 2 * Math.max(64, codeEntryAlignment) /* 2 * CodeSection::end_slop() */ +
+ 2 * 128 /* sizeof(relocInfo) * PhaseOutput::MAX_locs_size */;
+ // minimum size: CompilerConfig::min_code_cache_size =
+ // CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) + Compiler::code_buffer_size() + C2Compiler::initial_code_buffer_size())
+ long minSize = minUseSpace * (Platform.isDebugBuild() ? 3 : 1) + c1MinCodeCacheSize + c2MinCodeCacheSize;
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+SegmentedCodeCache",
"-XX:NonNMethodCodeHeapSize=" + minSize,
"-XX:ReservedCodeCacheSize=" + minSize,
diff --git a/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/libHiddenClassSigTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/libHiddenClassSigTest.cpp
index ad9da9e5301d5..b93d1fdd5d698 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/libHiddenClassSigTest.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/HiddenClass/libHiddenClassSigTest.cpp
@@ -23,6 +23,7 @@
#include
#include "jvmti.h"
+#include "jvmti_common.hpp"
extern "C" {
@@ -35,6 +36,9 @@ static jvmtiEnv *jvmti = nullptr;
static jint class_load_count = 0;
static jint class_prep_count = 0;
static bool failed = false;
+// JVMTI_ERROR_WRONG_PHASE guard
+static jrawMonitorID event_mon = nullptr;
+static bool is_vm_dead = false;
#define LOG0(str) { printf(str); fflush(stdout); }
#define LOG1(str, arg) { printf(str, arg); fflush(stdout); }
@@ -247,16 +251,21 @@ check_hidden_class_array(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass_array, const
LOG0("### Native agent: check_hidden_class_array finished\n");
}
-/* Process a CLASS_LOAD or aClassPrepare event. */
+/* Process a CLASS_LOAD or a ClassPrepare event. */
static void process_class_event(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass,
jint* event_count_ptr, const char* event_name) {
char* sig = nullptr;
char* gsig = nullptr;
jvmtiError err;
+ RawMonitorLocker locker(jvmti, jni, event_mon);
+ if (is_vm_dead) {
+ return;
+ }
+
// get class signature
err = jvmti->GetClassSignature(klass, &sig, &gsig);
- CHECK_JVMTI_ERROR(jni, err, "ClassLoad event: Error in JVMTI GetClassSignature");
+ CHECK_JVMTI_ERROR(jni, err, "ClassLoad/ClassPrepare event: Error in JVMTI GetClassSignature");
// check if this is an expected class event for hidden class
if (strlen(sig) > strlen(SIG_START) &&
@@ -301,6 +310,14 @@ VMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
CHECK_JVMTI_ERROR(jni, err, "VMInit event: Error in enabling ClassPrepare events notification");
}
+static void JNICALL
+VMDeath(jvmtiEnv *jvmti, JNIEnv* jni) {
+ RawMonitorLocker locker(jvmti, jni, event_mon);
+
+ LOG0("VMDeath\n");
+ is_vm_dead = true;
+}
+
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
jvmtiEventCallbacks callbacks;
@@ -313,11 +330,19 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
return JNI_ERR;
}
+ err = jvmti->CreateRawMonitor("Event Monitor", &event_mon);
+ if (err != JVMTI_ERROR_NONE) {
+ LOG1("Agent_OnLoad: CreateRawMonitor failed: %d\n", err);
+ failed = true;
+ return JNI_ERR;
+ }
+
// set required event callbacks
memset(&callbacks, 0, sizeof(callbacks));
callbacks.ClassLoad = &ClassLoad;
callbacks.ClassPrepare = &ClassPrepare;
callbacks.VMInit = &VMInit;
+ callbacks.VMDeath = &VMDeath;
err = jvmti->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
if (err != JVMTI_ERROR_NONE) {
diff --git a/test/hotspot/jtreg/serviceability/jvmti/VMObjectAlloc/libVMObjectAlloc.cpp b/test/hotspot/jtreg/serviceability/jvmti/VMObjectAlloc/libVMObjectAlloc.cpp
index 20b06c6648ef3..a4166322d7831 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/VMObjectAlloc/libVMObjectAlloc.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/VMObjectAlloc/libVMObjectAlloc.cpp
@@ -23,9 +23,15 @@
#include
#include "jvmti.h"
+#include "jvmti_common.hpp"
extern "C" {
+static jvmtiEnv *jvmti = nullptr;
+// JVMTI_ERROR_WRONG_PHASE guard
+static jrawMonitorID event_mon = nullptr;
+static bool is_vm_dead = false;
+
static int number_of_allocation = 0;
extern JNIEXPORT void JNICALL
@@ -35,19 +41,31 @@ VMObjectAlloc(jvmtiEnv *jvmti,
jobject object,
jclass cls,
jlong size) {
+ RawMonitorLocker locker(jvmti, jni, event_mon);
+ if (is_vm_dead) {
+ return;
+ }
+
char *signature = nullptr;
jvmtiError err = jvmti->GetClassSignature(cls, &signature, nullptr);
if (err != JVMTI_ERROR_NONE) {
jni->FatalError("Failed during the GetClassSignature call");
}
- printf("VMObjectAlloc called for %s\n", signature);
+ LOG("VMObjectAlloc called for %s\n", signature);
if (!strcmp(signature, "LVMObjectAllocTest;")) {
number_of_allocation++;
}
}
+static void JNICALL
+VMDeath(jvmtiEnv *jvmti, JNIEnv* jni) {
+ RawMonitorLocker locker(jvmti, jni, event_mon);
+
+ LOG("VMDeath\n");
+ is_vm_dead = true;
+}
JNIEXPORT jint JNICALL
Java_VMObjectAllocTest_getNumberOfAllocation(JNIEnv *env, jclass cls) {
@@ -56,7 +74,6 @@ Java_VMObjectAllocTest_getNumberOfAllocation(JNIEnv *env, jclass cls) {
extern JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
- jvmtiEnv *jvmti;
jvmtiEventCallbacks callbacks;
jvmtiError err;
jvmtiCapabilities caps;
@@ -65,8 +82,15 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
return JNI_ERR;
}
+ err = jvmti->CreateRawMonitor("Event Monitor", &event_mon);
+ if (err != JVMTI_ERROR_NONE) {
+ LOG("Agent_OnLoad: CreateRawMonitor failed: %d\n", err);
+ return JNI_ERR;
+ }
+
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMObjectAlloc = &VMObjectAlloc;
+ callbacks.VMDeath = &VMDeath;
memset(&caps, 0, sizeof(caps));
caps.can_generate_vm_object_alloc_events = 1;
diff --git a/test/jdk/com/sun/jdi/ReattachStressTest.java b/test/jdk/com/sun/jdi/ReattachStressTest.java
new file mode 100644
index 0000000000000..49206937f12fc
--- /dev/null
+++ b/test/jdk/com/sun/jdi/ReattachStressTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import jdk.test.lib.process.ProcessTools;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.AttachingConnector;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+
+/**
+ * @test
+ * @bug 8338708
+ * @summary Stress test for reattaching to a debuggee
+ * @library /test/lib
+ * @modules jdk.jdi
+ * @run driver ProcessAttachTest
+ */
+
+class ReattachStressTestTarg {
+ public static void main(String args[]) throws Exception {
+ System.out.println("Debuggee started");
+ while (true) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+}
+
+public class ReattachStressTest {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test 1: Debuggee start with suspend=n");
+ runTest("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n");
+
+ System.out.println("Test 2: Debuggee start with suspend=y");
+ runTest("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y");
+ }
+
+ private static void runTest(String jdwpArg) throws Exception {
+ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
+ jdwpArg,
+ "ReattachStressTestTarg");
+ Process p = null;
+ try {
+ p = pb.start();
+
+ // Read the first character of output to make sure we've waited until the
+ // debuggee is ready. This will be the debug agent's "Listening..." message.
+ InputStream is = p.getInputStream();
+ is.read();
+
+ // Attach a debugger
+ tryDebug(p.pid(), is);
+ } finally {
+ p.destroyForcibly();
+ }
+ }
+
+ private static void tryDebug(long pid, InputStream is) throws IOException,
+ IllegalConnectorArgumentsException {
+ // Get the ProcessAttachingConnector, which can attach using the pid of the debuggee.
+ AttachingConnector ac = Bootstrap.virtualMachineManager().attachingConnectors()
+ .stream()
+ .filter(c -> c.name().equals("com.sun.jdi.ProcessAttach"))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Unable to locate ProcessAttachingConnector"));
+
+ // Set the connector's "pid" argument to the pid of the debuggee.
+ Map args = ac.defaultArguments();
+ Connector.StringArgument arg = (Connector.StringArgument)args.get("pid");
+ arg.setValue("" + pid);
+
+ // Loop that will repeatedly attach and detach from the same debuggee.
+ for (int i = 0; i < 500; i++) {
+ System.out.println(i + ": Debugger is attaching to: " + pid + " ...");
+
+ // Attach to the debuggee.
+ VirtualMachine vm = ac.attach(args);
+
+ // Drain remaining "Listening..." output. Otherwise too much
+ // output will buffer up and the debuggee may block until it is cleared.
+ while (is.available() > 0) {
+ is.read();
+ }
+
+ // We've attached. Do some things that will send JDWP commands.
+ System.out.println("Attached!");
+ System.out.println("JVM name: " + vm.name());
+ System.out.println("Num threads: " + vm.allThreads().size());
+
+ // We're all done with this debugger connection.
+ vm.dispose();
+
+ // Wait for first char of next "Listening..." output.
+ is.read();
+ }
+ System.out.println("Debugger done.");
+ }
+}
diff --git a/test/jdk/java/foreign/TestFill.java b/test/jdk/java/foreign/TestFill.java
new file mode 100644
index 0000000000000..e5f69587f2f6c
--- /dev/null
+++ b/test/jdk/java/foreign/TestFill.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test MemorySegment::fill
+ * @run junit TestFill
+ */
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.ValueLayout;
+import java.util.Arrays;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+final class TestFill {
+
+ // Make sure negative values are treated as expected
+ private static final byte VALUE = -71;
+
+ @ParameterizedTest
+ @MethodSource("sizes")
+ void testFill(int len) {
+ int offset = 16;
+ int expandedLen = offset + MAX_SIZE + offset;
+
+ // Make sure fill only affects the intended region XXXXXX
+ //
+ // ................XXXXXX................
+ // | offset | len | offset |
+
+ try (var arena = Arena.ofConfined()) {
+ var segment = arena.allocate(expandedLen);
+ var slice = segment.asSlice(offset, len);
+ slice.fill(VALUE);
+
+ var expected = new byte[expandedLen];
+ Arrays.fill(expected, offset, offset + len, VALUE);
+
+ // This checks the actual fill region as well as potential under and overflows
+ assertArrayEquals(expected, segment.toArray(ValueLayout.JAVA_BYTE));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("values")
+ void testValues(int value) {
+ int size = 0b1111;
+ try (var arena = Arena.ofConfined()) {
+ var segment = arena.allocate(size);
+ segment.fill((byte) value);
+ assertTrue(segment.elements(ValueLayout.JAVA_BYTE)
+ .map(s -> s.get(ValueLayout.JAVA_BYTE, 0))
+ .allMatch(v -> v == value), "Failed to fill with value " + value);
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("sizes")
+ void testReadOnly(int len) {
+ try (var arena = Arena.ofConfined()) {
+ var segment = arena.allocate(10).asReadOnly();
+ assertThrows(IllegalArgumentException.class, () -> segment.fill(VALUE));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("sizes")
+ void testConfinement(int len) {
+ try (var arena = Arena.ofConfined()) {
+ var segment = arena.allocate(10);
+ AtomicReference ex = new AtomicReference<>();
+ CompletableFuture future = CompletableFuture.runAsync(() -> {
+ try {
+ segment.fill(VALUE);
+ } catch (RuntimeException e) {
+ ex.set(e);
+ }
+ });
+ future.join();
+ assertInstanceOf(WrongThreadException.class, ex.get());
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("sizes")
+ void testScope(int len) {
+ var arena = Arena.ofConfined();
+ var segment = arena.allocate(len);
+ arena.close();
+ assertThrows(IllegalStateException.class, () -> segment.fill(VALUE));
+ }
+
+ private static final int MAX_SIZE = 1 << 10;
+
+ private static Stream sizes() {
+ return IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 23, 32, 63, 128, 256, 511, MAX_SIZE)
+ .boxed()
+ .map(Arguments::of);
+ }
+
+ private static Stream values() {
+ return IntStream.rangeClosed(Byte.MIN_VALUE, Byte.MAX_VALUE)
+ .boxed()
+ .map(Arguments::of);
+ }
+
+}
diff --git a/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java b/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java
index 4e17408ee6f50..32c594808a9c4 100644
--- a/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java
+++ b/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -73,6 +73,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Flow;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiPredicate;
@@ -112,6 +113,7 @@ public class DependentPromiseActionsTest implements HttpServerAdapters {
static volatile boolean tasksFailed;
static final AtomicLong serverCount = new AtomicLong();
static final AtomicLong clientCount = new AtomicLong();
+ static final AtomicInteger requestCount = new AtomicInteger();
static final long start = System.nanoTime();
public static String now() {
long now = System.nanoTime() - start;
@@ -244,14 +246,17 @@ HttpClient newHttpClient(boolean share) {
}
@Test(dataProvider = "noStalls")
- public void testNoStalls(String uri, boolean sameClient)
+ public void testNoStalls(String rootUri, boolean sameClient)
throws Exception {
+ if (!FAILURES.isEmpty()) return;
HttpClient client = null;
- out.printf("%ntestNoStalls(%s, %b)%n", uri, sameClient);
+ out.printf("%ntestNoStalls(%s, %b)%n", rootUri, sameClient);
for (int i=0; i< ITERATION_COUNT; i++) {
if (!sameClient || client == null)
client = newHttpClient(sameClient);
+ String uri = rootUri + "/" + requestCount.incrementAndGet();
+ out.printf("\tsending request %s%n", uri);
HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
.build();
BodyHandler> handler =
@@ -331,6 +336,10 @@ private void testDependent(String name, String uri, boolean sameClient,
SubscriberType subscriberType)
throws Exception
{
+ if (!FAILURES.isEmpty()) {
+ out.printf("%s: skipping test - previous failure detected%n", name);
+ return;
+ }
out.printf("%n%s%s%n", now(), name);
try {
testDependent(uri, sameClient, handlers, finisher,
@@ -341,7 +350,7 @@ private void testDependent(String name, String uri, boolean sameClient,
}
}
- private void testDependent(String uri, boolean sameClient,
+ private void testDependent(String rootUri, boolean sameClient,
Supplier> handlers,
Finisher finisher,
Extractor extractor,
@@ -354,6 +363,8 @@ private void testDependent(String uri, boolean sameClient,
if (!sameClient || client == null)
client = newHttpClient(sameClient);
+ String uri = rootUri + "/" + requestCount.incrementAndGet();
+ out.printf("\tsending request %s%n", uri);
HttpRequest req = HttpRequest.
newBuilder(URI.create(uri))
.build();
@@ -363,7 +374,13 @@ private void testDependent(String uri, boolean sameClient,
System.out.println("try stalling in " + where);
CompletableFuture> responseCF =
client.sendAsync(req, handler, promiseHandler);
- assert subscriberType == SubscriberType.LAZZY || !responseCF.isDone();
+ // The body of the main response can be received before the body
+ // of the push promise handlers are received.
+ // The body of the main response doesn't stall, so the cf of
+ // the main response may be done here even for EAGER subscribers.
+ // We cannot make any assumption on the state of the main response
+ // cf here, so the only thing we can do is to call the finisher
+ // which will wait for them all.
finisher.finish(where, responseCF, promiseHandler, extractor);
}
}
diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java
index e07badd2bb7aa..7de14a79225a5 100644
--- a/test/jdk/java/net/httpclient/ProxyServer.java
+++ b/test/jdk/java/net/httpclient/ProxyServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -195,6 +195,9 @@ class Connection {
volatile InputStream clientIn, serverIn;
volatile OutputStream clientOut, serverOut;
+ boolean proxyInClosed; // only accessed from synchronized block
+ boolean proxyOutClosed; // only accessed from synchronized block
+
final static int CR = 13;
final static int LF = 10;
@@ -594,9 +597,7 @@ synchronized void proxyCommon(boolean log) throws IOException {
if (log)
System.out.printf("Proxy Forwarding [request body]: total %d%n", body);
}
- closing = true;
- serverSocket.close();
- clientSocket.close();
+ closeClientIn();
} catch (IOException e) {
if (!closing && debug) {
System.out.println("Proxy: " + e);
@@ -615,9 +616,7 @@ synchronized void proxyCommon(boolean log) throws IOException {
if (log) System.out.printf("Proxy Forwarding [response]: %s%n", new String(bb, 0, n, UTF_8));
if (log) System.out.printf("Proxy Forwarding [response]: total %d%n", resp);
}
- closing = true;
- serverSocket.close();
- clientSocket.close();
+ closeClientOut();
} catch (IOException e) {
if (!closing && debug) {
System.out.println("Proxy: " + e);
@@ -641,6 +640,28 @@ void doTunnel(String dest) throws IOException {
proxyCommon(false);
}
+ synchronized void closeClientIn() throws IOException {
+ closing = true;
+ proxyInClosed = true;
+ clientSocket.shutdownInput();
+ serverSocket.shutdownOutput();
+ if (proxyOutClosed) {
+ serverSocket.close();
+ clientSocket.close();
+ }
+ }
+
+ synchronized void closeClientOut() throws IOException {
+ closing = true;
+ proxyOutClosed = true;
+ serverSocket.shutdownInput();
+ clientSocket.shutdownOutput();
+ if (proxyInClosed) {
+ serverSocket.close();
+ clientSocket.close();
+ }
+ }
+
@Override
public String toString() {
return "Proxy connection " + id + ", client sock:" + clientSocket;
diff --git a/test/jdk/jdk/classfile/AdaptCodeTest.java b/test/jdk/jdk/classfile/AdaptCodeTest.java
index ca9145d688521..80c526c63c736 100644
--- a/test/jdk/jdk/classfile/AdaptCodeTest.java
+++ b/test/jdk/jdk/classfile/AdaptCodeTest.java
@@ -95,7 +95,7 @@ void testSevenOfThirteenIterator() throws Exception {
if ((val instanceof Integer) && ((Integer) val) == 13) {
val = 7;
}
- codeB.loadConstant(i.opcode(), val);
+ codeB.loadConstant(val);
}
default -> codeB.with(codeE);
}
diff --git a/test/jdk/jdk/classfile/LDCTest.java b/test/jdk/jdk/classfile/LDCTest.java
index 7379218840e30..207d53e88204c 100644
--- a/test/jdk/jdk/classfile/LDCTest.java
+++ b/test/jdk/jdk/classfile/LDCTest.java
@@ -64,9 +64,9 @@ void testLDCisConvertedToLDCW() throws Exception {
for (int i = 0; i <= 256/2 + 2; i++) { // two entries per String
StringEntry s = cpb.stringEntry("string" + i);
}
- c0.loadConstant(LDC, "string0")
- .loadConstant(LDC, "string131")
- .loadConstant(LDC, "string50")
+ c0.ldc("string0")
+ .ldc("string131")
+ .ldc("string50")
.loadConstant(-0.0f)
.loadConstant(-0.0d)
//non-LDC test cases
diff --git a/test/jdk/jdk/classfile/OpcodesValidationTest.java b/test/jdk/jdk/classfile/OpcodesValidationTest.java
index f44bdfd272559..2470fcf132c54 100644
--- a/test/jdk/jdk/classfile/OpcodesValidationTest.java
+++ b/test/jdk/jdk/classfile/OpcodesValidationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -23,107 +23,29 @@
/*
* @test
- * @summary Testing ClassFile constant instruction opcodes.
+ * @summary Testing ClassFile constant instruction argument validation.
* @run junit OpcodesValidationTest
*/
-import java.lang.constant.ClassDesc;
-import java.lang.constant.ConstantDesc;
-import static java.lang.constant.ConstantDescs.CD_void;
-import java.lang.constant.MethodTypeDesc;
+import java.lang.classfile.instruction.ConstantInstruction;
+import org.junit.jupiter.api.Test;
-import java.lang.reflect.AccessFlag;
-import java.lang.classfile.ClassFile;
-import java.lang.classfile.Opcode;
-import org.junit.jupiter.api.*;
-import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import static org.junit.jupiter.api.Assertions.*;
import static java.lang.classfile.Opcode.*;
-import java.util.stream.Stream;
-public class OpcodesValidationTest {
-
- record Case(Opcode opcode, Object constant) {}
-
- static Stream positiveCases() {
- return Stream.of(
- new Case(ACONST_NULL, null),
- new Case(SIPUSH, (int)Short.MIN_VALUE),
- new Case(SIPUSH, (int)Short.MAX_VALUE),
- new Case(BIPUSH, (int)Byte.MIN_VALUE),
- new Case(BIPUSH, (int)Byte.MAX_VALUE),
- new Case(ICONST_M1, -1),
- new Case(ICONST_0, 0),
- new Case(ICONST_1, 1),
- new Case(ICONST_2, 2),
- new Case(ICONST_3, 3),
- new Case(ICONST_4, 4),
- new Case(ICONST_5, 5),
- new Case(LCONST_0, 0l),
- new Case(LCONST_0, 0),
- new Case(LCONST_1, 1l),
- new Case(LCONST_1, 1),
- new Case(FCONST_0, 0.0f),
- new Case(FCONST_1, 1.0f),
- new Case(FCONST_2, 2.0f),
- new Case(DCONST_0, 0.0d),
- new Case(DCONST_1, 1.0d)
- );
- }
-
- static Stream negativeCases() {
- return Stream.of(
- new Case(ACONST_NULL, 0),
- new Case(SIPUSH, (int)Short.MIN_VALUE - 1),
- new Case(SIPUSH, (int)Short.MAX_VALUE + 1),
- new Case(BIPUSH, (int)Byte.MIN_VALUE - 1),
- new Case(BIPUSH, (int)Byte.MAX_VALUE + 1),
- new Case(ICONST_M1, -1l),
- new Case(ICONST_0, 0l),
- new Case(ICONST_1, 1l),
- new Case(ICONST_2, 2l),
- new Case(ICONST_3, 3l),
- new Case(ICONST_4, 4l),
- new Case(ICONST_5, 5l),
- new Case(LCONST_0, null),
- new Case(LCONST_0, 1l),
- new Case(LCONST_1, 1.0d),
- new Case(LCONST_1, 0),
- new Case(FCONST_0, 0.0d),
- new Case(FCONST_1, 1.01f),
- new Case(FCONST_2, 2),
- new Case(DCONST_0, 0.0f),
- new Case(DCONST_1, 1.0f),
- new Case(DCONST_1, 1)
- );
- }
-
- @TestFactory
- Stream testPositiveCases() {
- return positiveCases().map(c -> dynamicTest(c.toString(), () -> testPositiveCase(c.opcode, c.constant)));
- }
-
- private void testPositiveCase(Opcode opcode, Object constant) {
- ClassFile.of().build(ClassDesc.of("MyClass"),
- cb -> cb.withFlags(AccessFlag.PUBLIC)
- .withMethod("", MethodTypeDesc.of(CD_void), 0,
- mb -> mb.withCode(
- codeb -> codeb.loadConstant(opcode, (ConstantDesc) constant))));
- }
-
-
- @TestFactory
- Stream testNegativeCases() {
- return negativeCases().map(c -> dynamicTest(
- c.toString(),
- () -> assertThrows(IllegalArgumentException.class, () -> testNegativeCase(c.opcode, c.constant))
- ));
- }
-
- private void testNegativeCase(Opcode opcode, Object constant) {
- ClassFile.of().build(ClassDesc.of("MyClass"),
- cb -> cb.withFlags(AccessFlag.PUBLIC)
- .withMethod("", MethodTypeDesc.of(CD_void), 0,
- mb -> mb .withCode(
- codeb -> codeb.loadConstant(opcode, (ConstantDesc)constant))));
+class OpcodesValidationTest {
+
+ @Test
+ void testArgumentConstant() {
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, 0));
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, Short.MIN_VALUE));
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(SIPUSH, Short.MAX_VALUE));
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, 0));
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, Byte.MIN_VALUE));
+ assertDoesNotThrow(() -> ConstantInstruction.ofArgument(BIPUSH, Byte.MAX_VALUE));
+
+ assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(SIPUSH, (int)Short.MIN_VALUE - 1));
+ assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(SIPUSH, (int)Short.MAX_VALUE + 1));
+ assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int)Byte.MIN_VALUE - 1));
+ assertThrows(IllegalArgumentException.class, () -> ConstantInstruction.ofArgument(BIPUSH, (int)Byte.MAX_VALUE + 1));
}
}
diff --git a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java
index d7d9e9c267f51..d865ddad5edb2 100644
--- a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java
+++ b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -77,7 +77,7 @@ public static void toBuilder(CodeElement model, CodeBuilder cb) {
case OperatorInstruction im ->
cb.with(OperatorInstruction.of(im.opcode()));
case ConstantInstruction im ->
- cb.loadConstant(im.opcode(), im.constantValue());
+ cb.loadConstant(im.constantValue());
case MonitorInstruction im ->
cb.with(MonitorInstruction.of(im.opcode()));
case NopInstruction im ->
diff --git a/test/jdk/sun/java2d/Disposer/TestDisposerRace.java b/test/jdk/sun/java2d/Disposer/TestDisposerRace.java
index e22e59799515c..b78966f1200b2 100644
--- a/test/jdk/sun/java2d/Disposer/TestDisposerRace.java
+++ b/test/jdk/sun/java2d/Disposer/TestDisposerRace.java
@@ -23,6 +23,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
import javax.swing.SwingUtilities;
import sun.java2d.Disposer;
@@ -39,16 +40,23 @@ public final class TestDisposerRace {
private static final AtomicInteger recordsCount = new AtomicInteger();
private static volatile boolean disposerDone = false;
+ private static final String KO_OVERFLOW = "Some records have not been disposed!";
+ private static final String KO_UNDERFLOW = "Disposed more records than were added!";
+
public static void main(String[] args) throws Exception {
- TestDisposerRace test = new TestDisposerRace();
- test.run();
+ new TestDisposerRace().run();
checkRecordsCountIsSane();
if (recordsCount.get() > 0) {
+ System.err.println(KO_OVERFLOW); // In case the next line fails to allocate due to OOME
throw new RuntimeException("Some records (" + recordsCount + ") have not been disposed");
}
}
+ interface ThrowingRunnable {
+ void run() throws E;
+ }
+
TestDisposerRace() {
addRecordsToDisposer(30_000);
}
@@ -56,14 +64,14 @@ public static void main(String[] args) throws Exception {
void run() throws Exception {
generateOOME();
for (int i = 0; i < 1000; ++i) {
- SwingUtilities.invokeAndWait(Disposer::pollRemove);
- if (i % 10 == 0) {
- // Adding records will race with the diposer trying to remove them
+ retryOnOOME(() -> SwingUtilities.invokeAndWait(Disposer::pollRemove));
+
+ // Adding records will race with the diposer trying to remove them
+ if (i % 10 == 0)
addRecordsToDisposer(1000);
- }
}
- Disposer.addObjectRecord(new Object(), new FinalDisposerRecord());
+ retryOnOOME(() -> Disposer.addObjectRecord(new Object(), new FinalDisposerRecord()));
while (!disposerDone) {
generateOOME();
@@ -72,18 +80,45 @@ void run() throws Exception {
private static void checkRecordsCountIsSane() {
if (recordsCount.get() < 0) {
- throw new RuntimeException("Disposed more records than were added");
+ throw new RuntimeException(KO_UNDERFLOW);
+ }
+ }
+
+ private static T retryOnOOME(Supplier allocator) {
+ for(;;) {
+ try {
+ return allocator.get();
+ } catch (OutOfMemoryError ignored1) {
+ try {
+ Thread.sleep(1); // Give GC a little chance to run
+ } catch (InterruptedException ignored2) {}
+ }
+ }
+ }
+
+ private static void retryOnOOME(ThrowingRunnable tr) throws E {
+ for(;;) {
+ try {
+ tr.run();
+ break;
+ } catch (OutOfMemoryError ignored1) {
+ try {
+ Thread.sleep(1); // Give GC a little chance to run
+ } catch (InterruptedException ignored2) {}
+ }
}
}
private void addRecordsToDisposer(int count) {
checkRecordsCountIsSane();
- recordsCount.addAndGet(count);
+ MyDisposerRecord disposerRecord = retryOnOOME(MyDisposerRecord::new);
- MyDisposerRecord disposerRecord = new MyDisposerRecord();
- for (int i = 0; i < count; i++) {
- Disposer.addObjectRecord(new Object(), disposerRecord);
+ while(count > 0) {
+ recordsCount.incrementAndGet(); // pre-add to make sure it doesn't go negative
+ var o = retryOnOOME(Object::new);
+ retryOnOOME(() -> Disposer.addObjectRecord(o, disposerRecord));
+ --count;
}
}
@@ -106,8 +141,8 @@ private static void giveGCAChance() {
}
private static void generateOOME() throws Exception {
- final List