Skip to content

Commit 8339260

Browse files
plummercjpull[bot]
authored andcommitted
8332488: Add JVMTI DataDumpRequest to the debug agent
Reviewed-by: sspitsyn, lmesnik
1 parent a37986b commit 8339260

File tree

10 files changed

+251
-37
lines changed

10 files changed

+251
-37
lines changed

src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -995,6 +995,8 @@ parseOptions(char *options)
995995
gdata->includeVThreads = JNI_FALSE;
996996
gdata->rememberVThreadsWhenDisconnected = JNI_FALSE;
997997

998+
gdata->jvmti_data_dump = JNI_FALSE;
999+
9981000
/* Options being NULL will end up being an error. */
9991001
if (options == NULL) {
10001002
options = "";
@@ -1159,6 +1161,13 @@ parseOptions(char *options)
11591161
if ( dopause ) {
11601162
do_pause();
11611163
}
1164+
} else if (strcmp(buf, "datadump") == 0) {
1165+
// Enable JVMTI DATA_DUMP_REQUEST support.
1166+
// This is not a documented flag. This feature is experimental and is only intended
1167+
// to be used by debug agent developers. See comment for cbDataDump() for more details.
1168+
if ( !get_boolean(&str, &(gdata->jvmti_data_dump)) ) {
1169+
goto syntax_error;
1170+
}
11621171
} else if (strcmp(buf, "coredump") == 0) {
11631172
if ( !get_boolean(&str, &docoredump) ) {
11641173
goto syntax_error;

src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -1387,9 +1387,7 @@ eventFilterRestricted_deinstall(HandlerNode *node)
13871387
return error1 != JVMTI_ERROR_NONE? error1 : error2;
13881388
}
13891389

1390-
/***** debugging *****/
1391-
1392-
#ifdef DEBUG
1390+
/***** APIs for debugging the debug agent *****/
13931391

13941392
void
13951393
eventFilter_dumpHandlerFilters(HandlerNode *node)
@@ -1476,5 +1474,3 @@ eventFilter_dumpHandlerFilters(HandlerNode *node)
14761474
}
14771475
}
14781476
}
1479-
1480-
#endif /* DEBUG */

src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -76,10 +76,8 @@ jvmtiError eventFilter_setPlatformThreadsOnlyFilter(HandlerNode *node, jint inde
7676
jboolean eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname);
7777
jboolean isBreakpointSet(jclass clazz, jmethodID method, jlocation location);
7878

79-
/***** debugging *****/
79+
/***** APIs for debugging the debug agent *****/
8080

81-
#ifdef DEBUG
8281
void eventFilter_dumpHandlerFilters(HandlerNode *node);
83-
#endif
8482

8583
#endif /* _EVENT_FILTER_H */

src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,44 @@ cbVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env)
13301330
LOG_MISC(("END cbVMDeath"));
13311331
}
13321332

1333+
/**
1334+
* Event callback for JVMTI_EVENT_DATA_DUMP_REQUEST
1335+
*
1336+
* This callback is made when a JVMTI data dump is requested. The common way of doing
1337+
* this is with "jcmd <pid> JVMTI.data_dump".
1338+
*
1339+
* Debug agent data dumps are experimental and only intended to be used by debug agent
1340+
* developers. Data dumps are disabled by default.
1341+
*
1342+
* This callback is enabled by launching the debug agent with datadump=y. The easiest
1343+
* way to enabled data dumps with debugger tests or when using jdb is to use the
1344+
* _JAVA_JDWP_OPTIONS export. The following works well when running tests:
1345+
*
1346+
* make test TEST=<test> \
1347+
* JTREG='JAVA_OPTIONS=-XX:+StartAttachListener;OPTIONS=-e:_JAVA_JDWP_OPTIONS=datadump=y'
1348+
*
1349+
* Data dumps may fail to happen due to the debug agent suspending all threads.
1350+
* This causes the Signal Dispatcher and Attach Listener threads to be suspended,
1351+
* which can cause issues with jcmd attaching. Running with -XX:+StartAttachListener can
1352+
* help, but in general it is best not to try a datadump when all threads are suspended.
1353+
*
1354+
* Data dumps are also risky when the debug agent is handling events or commands from
1355+
* the debugger, due to dumping data that is not lock protected. This can cause a
1356+
* crash.
1357+
*
1358+
* Data dumps are meant to aid with post mortem debugging (debugging after a
1359+
* problem has been detected), not for ongoing periodic data gathering.
1360+
*/
1361+
static void JNICALL
1362+
cbDataDump(jvmtiEnv *jvmti_env)
1363+
{
1364+
tty_message("Debug Agent Data Dump");
1365+
tty_message("=== START DUMP ===");
1366+
threadControl_dumpAllThreads();
1367+
eventHandler_dumpAllHandlers(JNI_TRUE);
1368+
tty_message("=== END DUMP ===");
1369+
}
1370+
13331371
/**
13341372
* Delete this handler (do not delete permanent handlers):
13351373
* Deinsert handler from active list,
@@ -1518,6 +1556,19 @@ eventHandler_initialize(jbyte sessionID)
15181556
if (error != JVMTI_ERROR_NONE) {
15191557
EXIT_ERROR(error,"Can't enable garbage collection finish events");
15201558
}
1559+
1560+
/*
1561+
* DATA_DUMP_REQUEST is special since it is not tied to any handlers or an EI,
1562+
* so it cannot be setup using threadControl_setEventMode(). Use JVMTI API directly.
1563+
*/
1564+
if (gdata->jvmti_data_dump) {
1565+
error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
1566+
(gdata->jvmti, JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
1567+
if (error != JVMTI_ERROR_NONE) {
1568+
EXIT_ERROR(error,"Can't enable data dump request events");
1569+
}
1570+
}
1571+
15211572
/*
15221573
* Only enable vthread START and END events if we want to remember
15231574
* vthreads when no debugger is connected.
@@ -1580,6 +1631,8 @@ eventHandler_initialize(jbyte sessionID)
15801631
gdata->callbacks.VirtualThreadStart = &cbVThreadStart;
15811632
/* Event callback for JVMTI_EVENT_VIRTUAL_THREAD_END */
15821633
gdata->callbacks.VirtualThreadEnd = &cbVThreadEnd;
1634+
/* Event callback for JVMTI_EVENT_DATA_DUMP_REQUEST */
1635+
gdata->callbacks.DataDumpRequest = &cbDataDump;
15831636

15841637
error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
15851638
(gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
@@ -1851,9 +1904,7 @@ eventHandler_installExternal(HandlerNode *node)
18511904
JNI_TRUE);
18521905
}
18531906

1854-
/***** debugging *****/
1855-
1856-
#ifdef DEBUG
1907+
/***** APIs for debugging the debug agent *****/
18571908

18581909
void
18591910
eventHandler_dumpAllHandlers(jboolean dumpPermanent)
@@ -1892,5 +1943,3 @@ eventHandler_dumpHandler(HandlerNode *node)
18921943
tty_message("Handler for %s(%d)\n", eventIndex2EventName(node->ei), node->ei);
18931944
eventFilter_dumpHandlerFilters(node);
18941945
}
1895-
1896-
#endif /* DEBUG */

src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,10 @@ jboolean eventHandler_synthesizeUnloadEvent(char *signature, JNIEnv *env);
8585

8686
jclass getMethodClass(jvmtiEnv *jvmti_env, jmethodID method);
8787

88-
/***** debugging *****/
88+
/***** APIs for debugging the debug agent *****/
8989

90-
#ifdef DEBUG
9190
void eventHandler_dumpAllHandlers(jboolean dumpPermanent);
9291
void eventHandler_dumpHandlers(EventIndex ei, jboolean dumpPermanent);
9392
void eventHandler_dumpHandler(HandlerNode *node);
94-
#endif
9593

9694
#endif /* _EVENTHANDLER_H */

src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,6 @@ typedef struct {
137137

138138
static DeferredEventModeList deferredEventModes;
139139

140-
#ifdef DEBUG
141-
static void dumpThreadList(ThreadList *list);
142-
static void dumpThread(ThreadNode *node);
143-
#endif
144-
145140
/* Get the state of the thread direct from JVMTI */
146141
static jvmtiError
147142
threadState(jthread thread, jint *pstate)
@@ -2561,13 +2556,15 @@ threadControl_allVThreads(jint *numVThreads)
25612556
return vthreads;
25622557
}
25632558

2564-
/***** debugging *****/
2559+
/***** APIs for debugging the debug agent *****/
25652560

2566-
#ifdef DEBUG
2561+
static void dumpThreadList(ThreadList *list);
2562+
static void dumpThread(ThreadNode *node);
25672563

25682564
void
25692565
threadControl_dumpAllThreads()
25702566
{
2567+
tty_message("suspendAllCount: %d", suspendAllCount);
25712568
tty_message("Dumping runningThreads:");
25722569
dumpThreadList(&runningThreads);
25732570
tty_message("\nDumping runningVThreads:");
@@ -2652,5 +2649,3 @@ dumpThread(ThreadNode *node) {
26522649
tty_message("\tobjID: %d", commonRef_refToID(getEnv(), node->thread));
26532650
#endif
26542651
}
2655-
2656-
#endif /* DEBUG */

src/jdk.jdwp.agent/share/native/libjdwp/threadControl.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,9 @@ jlong threadControl_getFrameGeneration(jthread thread);
7676

7777
jthread *threadControl_allVThreads(jint *numVThreads);
7878

79-
/***** debugging *****/
79+
/***** APIs for debugging the debug agent *****/
8080

81-
#ifdef DEBUG
8281
void threadControl_dumpAllThreads();
8382
void threadControl_dumpThread(jthread thread);
84-
#endif
8583

8684
#endif

src/jdk.jdwp.agent/share/native/libjdwp/util.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,8 +1984,6 @@ eventIndex2jvmti(EventIndex ei)
19841984
return event;
19851985
}
19861986

1987-
#ifdef DEBUG
1988-
19891987
char*
19901988
eventIndex2EventName(EventIndex ei)
19911989
{
@@ -2040,8 +2038,6 @@ eventIndex2EventName(EventIndex ei)
20402038
}
20412039
}
20422040

2043-
#endif
2044-
20452041
EventIndex
20462042
jdwp2EventIndex(jdwpEvent eventType)
20472043
{

src/jdk.jdwp.agent/share/native/libjdwp/util.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ typedef struct {
9090
jboolean doerrorexit;
9191
jboolean modifiedUtf8;
9292
jboolean quiet;
93+
jboolean jvmti_data_dump; /* If true, then support JVMTI DATA_DUMP_REQUEST events. */
9394

9495
/* Debug flags (bit mask) */
9596
int debugflags;
@@ -389,9 +390,7 @@ void *jvmtiAllocate(jint numBytes);
389390
void jvmtiDeallocate(void *buffer);
390391

391392
void eventIndexInit(void);
392-
#ifdef DEBUG
393393
char* eventIndex2EventName(EventIndex ei);
394-
#endif
395394
jdwpEvent eventIndex2jdwp(EventIndex i);
396395
jvmtiEvent eventIndex2jvmti(EventIndex i);
397396
EventIndex jdwp2EventIndex(jdwpEvent eventType);

0 commit comments

Comments
 (0)