Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/dump.c
6000 views
1
/*******************************************************************************
2
* Copyright (c) 1998, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "jni.h"
24
#include "j9.h"
25
#include "util_api.h"
26
#include "ut_j9jcl.h"
27
#include "rasdump_api.h"
28
29
#define COM_IBM_JVM_DUMP "com.ibm.jvm.Dump."
30
31
static void raiseExceptionFor(JNIEnv *env, omr_error_t result);
32
33
/*
34
* Cause a HeapDump to be caused.
35
*
36
* Returns the return value of the creation - 0 on success.
37
*/
38
jint JNICALL
39
Java_com_ibm_jvm_Dump_HeapDumpImpl(JNIEnv *env, jclass clazz)
40
{
41
J9VMThread *thr = (J9VMThread *)env;
42
J9JavaVM *vm = thr->javaVM;
43
omr_error_t rc = vm->j9rasDumpFunctions->triggerOneOffDump(vm, "heap", "com.ibm.jvm.Dump.HeapDump", NULL, 0);
44
45
return omrErrorCodeToJniErrorCode(rc);
46
}
47
48
/*
49
* Cause a JavaDump to be caused.
50
*
51
* Returns the return value of the creation - 0 on success.
52
*/
53
jint JNICALL
54
Java_com_ibm_jvm_Dump_JavaDumpImpl(JNIEnv *env, jclass clazz)
55
{
56
J9VMThread *thr = (J9VMThread *)env;
57
J9JavaVM *vm = thr->javaVM;
58
omr_error_t rc = vm->j9rasDumpFunctions->triggerOneOffDump(vm, "java", "com.ibm.jvm.Dump.JavaDump", NULL, 0);
59
60
return omrErrorCodeToJniErrorCode(rc);
61
}
62
63
/*
64
* Cause a SystemDump to be caused.
65
*
66
* Returns the return value of the creation - 0 on success.
67
*/
68
jint JNICALL
69
Java_com_ibm_jvm_Dump_SystemDumpImpl(JNIEnv *env, jclass clazz)
70
{
71
J9VMThread *thr = (J9VMThread *)env;
72
J9JavaVM *vm = thr->javaVM;
73
omr_error_t rc = vm->j9rasDumpFunctions->triggerOneOffDump(vm, "system", "com.ibm.jvm.Dump.SystemDump", NULL, 0);
74
75
return omrErrorCodeToJniErrorCode(rc);
76
}
77
78
/*
79
* Cause a SnapDump to be caused.
80
*
81
* Returns the return value of the creation - 0 on success.
82
*/
83
jint JNICALL
84
Java_com_ibm_jvm_Dump_SnapDumpImpl(JNIEnv *env, jclass clazz) {
85
J9VMThread *thr = (J9VMThread *)env;
86
J9JavaVM *vm = thr->javaVM;
87
omr_error_t rc = vm->j9rasDumpFunctions->triggerOneOffDump(vm, "Snap", "com.ibm.jvm.Dump.SnapDump", NULL, 0);
88
89
return omrErrorCodeToJniErrorCode(rc);
90
}
91
92
/* Scan the dump type string for "tool". Done in C to make sure we
93
* can use the same logic as the dump code and avoid anyone doing
94
* anything clever like finding multiple UTF-8 characters that map
95
* to the ascii letters for "tool".
96
*/
97
static jboolean scanDumpTypeForToolDump(char **typeString)
98
{
99
/* Check for the string "tool" as a dump type. (Appears before + or :) */
100
char *endPtr = *typeString + strlen(*typeString);
101
102
if( strchr(*typeString, ':') != NULL ) {
103
endPtr = strchr(*typeString, ':');
104
}
105
106
do {
107
/* Check for a tool dump option. */
108
if( try_scan(typeString, "tool") ) {
109
110
/* Check for a well-formed dump option */
111
if ( *typeString[0] == '+' ||
112
*typeString[0] == ':' ||
113
*typeString[0] == '\0' ) {
114
return JNI_TRUE;
115
}
116
} else {
117
/* Any more dump types? */
118
if( strchr(*typeString, '+') != NULL ) {
119
*typeString = strchr(*typeString, '+') + 1;
120
} else {
121
break; /* No more dump types. */
122
}
123
}
124
} while ( *typeString < endPtr);
125
126
return JNI_FALSE;
127
}
128
129
jboolean JNICALL
130
Java_com_ibm_jvm_Dump_isToolDump(JNIEnv *env, jclass clazz, jstring jopts) {
131
char *optsBuffer = NULL;
132
int optsLength = 0;
133
jboolean retVal = JNI_FALSE;
134
135
PORT_ACCESS_FROM_ENV(env);
136
137
if( jopts == NULL ) {
138
return FALSE;
139
}
140
141
optsLength = (*env)->GetStringUTFLength(env, jopts);
142
optsBuffer = j9mem_allocate_memory(optsLength+1, J9MEM_CATEGORY_VM_JCL);
143
144
if( optsBuffer != NULL ) {
145
char * optsBufferPtr = optsBuffer;
146
memset(optsBuffer, 0, optsLength+1);
147
(*env)->GetStringUTFRegion(env, jopts, 0, optsLength, optsBuffer);
148
149
retVal = scanDumpTypeForToolDump(&optsBufferPtr);
150
151
j9mem_free_memory(optsBuffer);
152
} else {
153
jclass exceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
154
if (exceptionClass != NULL) {
155
(*env)->ThrowNew(env, exceptionClass, "Out of memory triggering dump");
156
}
157
/* Just return if we can't load the exception class. */
158
retVal = JNI_FALSE;
159
}
160
return retVal;
161
}
162
163
jstring JNICALL
164
Java_com_ibm_jvm_Dump_triggerDumpsImpl (JNIEnv *env, jclass clazz, jstring jopts, jstring jevent)
165
{
166
J9VMThread *thr = (J9VMThread *)env;
167
J9JavaVM *vm = thr->javaVM;
168
char *optsBuffer = NULL;
169
char *eventBuffer = NULL;
170
char fileName[EsMaxPath+1];
171
int optsLength = 0;
172
int eventLength = 0;
173
omr_error_t result = OMR_ERROR_NONE;
174
jstring toReturn = NULL;
175
176
PORT_ACCESS_FROM_ENV(env);
177
178
/* Java code will have checked jopts is not null. */
179
optsLength = (*env)->GetStringUTFLength(env, jopts);
180
eventLength = (*env)->GetStringUTFLength(env, jevent);
181
182
optsBuffer = j9mem_allocate_memory(optsLength+1, J9MEM_CATEGORY_VM_JCL);
183
eventBuffer = j9mem_allocate_memory(strlen(COM_IBM_JVM_DUMP) + eventLength + 1, J9MEM_CATEGORY_VM_JCL);
184
185
186
/* Copy the file name string, avoid holding locks on things. */
187
if( optsBuffer != NULL && eventBuffer != NULL) {
188
189
memset(optsBuffer, 0, optsLength+1);
190
memset(eventBuffer, 0, strlen(COM_IBM_JVM_DUMP) + eventLength + 1);
191
/* Prefix the dump detail with com.ibm.jvm.Dump so createOneOffDumpAgent can
192
* be sure of the source and prevent tool dumps from being run. (Avoiding
193
* a back door to Runtime.exec() )
194
*/
195
strcpy(eventBuffer, COM_IBM_JVM_DUMP);
196
memset(fileName, 0, sizeof(fileName));
197
198
(*env)->GetStringUTFRegion(env, jopts, 0, optsLength, optsBuffer);
199
(*env)->GetStringUTFRegion(env, jevent, 0, eventLength, eventBuffer + strlen(eventBuffer));
200
201
result = vm->j9rasDumpFunctions->triggerOneOffDump(vm, optsBuffer, eventBuffer, fileName, sizeof(fileName));
202
203
if (OMR_ERROR_NONE == result) {
204
jstring actualFile = NULL;
205
actualFile = (*env)->NewStringUTF(env, fileName);
206
toReturn = actualFile;
207
} else {
208
raiseExceptionFor(env, result);
209
}
210
} else {
211
jclass exceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
212
if (exceptionClass != NULL) {
213
(*env)->ThrowNew(env, exceptionClass, "Out of memory triggering dump");
214
}
215
/* Just return if we can't load the exception class. */
216
}
217
if( optsBuffer != NULL ) {
218
j9mem_free_memory(optsBuffer);
219
}
220
if( eventBuffer != NULL ) {
221
j9mem_free_memory(eventBuffer);
222
}
223
return toReturn;
224
}
225
226
jstring JNICALL
227
Java_openj9_internal_tools_attach_target_DiagnosticUtils_triggerDumpsImpl(JNIEnv *env, jclass clazz, jstring jopts, jstring jevent)
228
{
229
return Java_com_ibm_jvm_Dump_triggerDumpsImpl(env, clazz, jopts, jevent);
230
}
231
232
void JNICALL
233
Java_com_ibm_jvm_Dump_setDumpOptionsImpl (JNIEnv *env, jclass clazz, jstring jopts)
234
{
235
J9VMThread *thr = (J9VMThread *)env;
236
J9JavaVM *vm = thr->javaVM;
237
char *optsBuffer = NULL;
238
int optsLength = 0;
239
omr_error_t result = OMR_ERROR_NONE;
240
241
PORT_ACCESS_FROM_ENV(env);
242
243
/* Java code will have checked jopts is not null. */
244
optsLength = (*env)->GetStringUTFLength(env, jopts);
245
246
optsBuffer = j9mem_allocate_memory(optsLength+1, J9MEM_CATEGORY_VM_JCL);
247
248
if( optsBuffer != NULL ) {
249
memset(optsBuffer, 0, optsLength+1);
250
251
(*env)->GetStringUTFRegion(env, jopts, 0, optsLength, optsBuffer);
252
if (!(*env)->ExceptionCheck(env)) {
253
254
/* Pass option to the dump facade */
255
result = vm->j9rasDumpFunctions->setDumpOption(vm, optsBuffer);
256
257
/* Map back to exception */
258
if (OMR_ERROR_NONE != result) {
259
raiseExceptionFor(env, result);
260
}
261
}
262
} else {
263
jclass exceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
264
if (exceptionClass != NULL) {
265
(*env)->ThrowNew(env, exceptionClass, "Out of memory setting dump options");
266
}
267
/* Just return if we can't load the exception class as an exception will be pending. */
268
}
269
270
if( optsBuffer != NULL ) {
271
j9mem_free_memory(optsBuffer);
272
}
273
}
274
275
jstring JNICALL
276
Java_com_ibm_jvm_Dump_queryDumpOptionsImpl (JNIEnv *env, jclass clazz) {
277
278
#define BUFFER_SIZE 10240
279
280
J9VMThread *thr = (J9VMThread *)env;
281
J9JavaVM *vm = thr->javaVM;
282
jint buffer_size = BUFFER_SIZE;
283
char options_buffer[BUFFER_SIZE];
284
char* options_ptr = NULL;
285
jint data_size;
286
jint* data_size_ptr = &data_size;
287
jstring toReturn = NULL;
288
omr_error_t result = OMR_ERROR_NONE;
289
PORT_ACCESS_FROM_ENV(env);
290
291
memset(options_buffer, 0, buffer_size);
292
result = vm->j9rasDumpFunctions->queryVmDump(vm, buffer_size, options_buffer, data_size_ptr);
293
294
/* Insufficient buffer space, malloc. */
295
/* Retry in case someone is updating the agents while we run. */
296
while( data_size > buffer_size) {
297
buffer_size = data_size;
298
if( options_ptr != NULL ) {
299
j9mem_free_memory(options_ptr);
300
options_ptr = NULL;
301
}
302
options_ptr = j9mem_allocate_memory(buffer_size, J9MEM_CATEGORY_VM_JCL);
303
if( options_ptr != NULL ) {
304
memset(options_ptr, 0, buffer_size);
305
result = vm->j9rasDumpFunctions->queryVmDump(vm, buffer_size, options_ptr, data_size_ptr);
306
} else {
307
result = OMR_ERROR_OUT_OF_NATIVE_MEMORY;
308
break; /* malloc failed */
309
}
310
}
311
if (OMR_ERROR_NONE == result) {
312
if( options_ptr == NULL ) {
313
toReturn = (*env)->NewStringUTF(env, options_buffer);
314
} else {
315
toReturn = (*env)->NewStringUTF(env, options_ptr);
316
}
317
} else {
318
/* Map back to exception */
319
raiseExceptionFor(env, result);
320
}
321
if( options_ptr != NULL ) {
322
j9mem_free_memory(options_ptr);
323
}
324
325
return toReturn;
326
}
327
328
void JNICALL
329
Java_com_ibm_jvm_Dump_resetDumpOptionsImpl (JNIEnv *env, jclass clazz)
330
{
331
omr_error_t result = OMR_ERROR_NONE;
332
J9VMThread *thr = (J9VMThread *)env;
333
J9JavaVM *vm = thr->javaVM;
334
335
/* request dump reset from dump module */
336
result = vm->j9rasDumpFunctions->resetDumpOptions(vm);
337
338
/* Not much error handling we can do but this can fail if the dump configuration
339
* is locked while a dump is in progress. */
340
341
/* Map back to exception */
342
if (OMR_ERROR_NONE != result) {
343
raiseExceptionFor(env, result);
344
}
345
}
346
347
/**
348
* Raise exception for OMR error code that is passed in.
349
*
350
* Dump.queryDumpOptions() will never return DumpConfigurationUnavailableException according to the published API.
351
* Java_com_ibm_jvm_Dump_queryDumpOptionsImpl() calls raiseExceptionFor() only when queryVmDump() returns
352
* OMR_ERROR_OUT_OF_NATIVE_MEMORY, the return case of OMR_ERROR_ILLEGAL_ARGUMENT will never happen for raiseException().
353
*
354
* @param[in] env The JNIEnv* of the current thread.
355
* @param[in] result The OMR error code.
356
*/
357
static void
358
raiseExceptionFor(JNIEnv *env, omr_error_t result)
359
{
360
jclass exceptionClass = NULL;
361
362
switch (result) {
363
case OMR_ERROR_INTERNAL:
364
exceptionClass = (*env)->FindClass(env, "openj9/management/internal/InvalidDumpOptionExceptionBase");
365
if (exceptionClass != NULL) {
366
(*env)->ThrowNew(env, exceptionClass, "Error in dump options.");
367
}
368
/* Just return if we can't load the exception class. */
369
break;
370
case OMR_ERROR_OUT_OF_NATIVE_MEMORY:
371
exceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
372
if (exceptionClass != NULL) {
373
(*env)->ThrowNew(env, exceptionClass, "Out of memory setting dump option");
374
}
375
/* Just return if we can't load the exception class. */
376
break;
377
case OMR_ERROR_NOT_AVAILABLE:
378
exceptionClass = (*env)->FindClass(env, "openj9/management/internal/DumpConfigurationUnavailableExceptionBase");
379
if (exceptionClass != NULL) {
380
(*env)->ThrowNew(env, exceptionClass, "Dump configuration cannot be changed while a dump is in progress.");
381
}
382
/* Just return if we can't load the exception class. */
383
break;
384
default:
385
Assert_JCL_unreachable();
386
break;
387
}
388
}
389
390