Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/java_lang_StackWalker.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2017, 2022 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 "jcl.h"
25
#include "jclglob.h"
26
#include "jclprots.h"
27
#include "jcl_internal.h"
28
#include "objhelp.h"
29
#include "rommeth.h"
30
#include "vmaccess.h"
31
#include "VMHelpers.hpp"
32
33
extern "C" {
34
#define RETAIN_CLASS_REFERENCE 1
35
#define SHOW_REFLECT_FRAMES 2
36
#define SHOW_HIDDEN_FRAMES 4
37
#define FRAME_VALID 8
38
#define FRAME_FILTER_MASK (RETAIN_CLASS_REFERENCE | SHOW_REFLECT_FRAMES | SHOW_HIDDEN_FRAMES)
39
40
static UDATA stackFrameFilter(J9VMThread * currentThread, J9StackWalkState * walkState);
41
42
static UDATA
43
stackFrameFilter(J9VMThread * currentThread, J9StackWalkState * walkState)
44
{
45
/*
46
* userData1 contains filtering flags, i.e. show hidden, show reflect.
47
* userData2 contains stackWalkerMethod, the method name to search for
48
*/
49
UDATA result = J9_STACKWALK_STOP_ITERATING;
50
51
if (NULL != walkState->userData2) { /* look for stackWalkerMethod */
52
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method);
53
J9ROMClass *romClass = J9_CLASS_FROM_METHOD(walkState->method)->romClass;
54
55
J9UTF8 *utf = J9ROMMETHOD_NAME(romMethod);
56
const char *stackWalkerMethod = (const char *) walkState->userData2;
57
result = J9_STACKWALK_KEEP_ITERATING;
58
59
if (compareUTF8Length(J9UTF8_DATA(utf), J9UTF8_LENGTH(utf), (void *) stackWalkerMethod, strlen(stackWalkerMethod)) == 0) {
60
utf = J9ROMCLASS_CLASSNAME(romClass);
61
if (J9UTF8_LITERAL_EQUALS(J9UTF8_DATA(utf), J9UTF8_LENGTH(utf), "java/lang/StackWalker")) {
62
walkState->userData2 = NULL; /* Iteration will skip hidden frames and stop at the true caller of stackWalkerMethod. */
63
}
64
}
65
} else if (J9_ARE_NO_BITS_SET((UDATA) (walkState->userData1), SHOW_REFLECT_FRAMES | SHOW_HIDDEN_FRAMES)
66
&& VM_VMHelpers::isReflectionMethod(currentThread, walkState->method)
67
) {
68
/* skip reflection/MethodHandleInvoke frames */
69
result = J9_STACKWALK_KEEP_ITERATING;
70
} else {
71
result = J9_STACKWALK_STOP_ITERATING;
72
}
73
74
return result;
75
}
76
77
jobject JNICALL
78
Java_java_lang_StackWalker_walkWrapperImpl(JNIEnv *env, jclass clazz, jint flags, jstring stackWalkerMethod, jobject function)
79
{
80
J9VMThread *vmThread = (J9VMThread *) env;
81
J9JavaVM *vm = vmThread->javaVM;
82
83
J9StackWalkState newWalkState;
84
J9StackWalkState *walkState = vmThread->stackWalkState;
85
86
Assert_JCL_notNull (stackWalkerMethod);
87
memset(&newWalkState, 0, sizeof(J9StackWalkState));
88
newWalkState.previous = walkState;
89
vmThread->stackWalkState = &newWalkState;
90
walkState->walkThread = vmThread;
91
walkState->flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_WALK_TRANSLATE_PC
92
| J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY;
93
/* If -XX:+ShowHiddenFrames and StackWalker.SHOW_HIDDEN_FRAMES option has not been set, skip hidden method frames */
94
if (J9_ARE_NO_BITS_SET(vm->runtimeFlags, J9_RUNTIME_SHOW_HIDDEN_FRAMES)
95
&& J9_ARE_NO_BITS_SET((UDATA)flags, SHOW_HIDDEN_FRAMES)
96
) {
97
walkState->flags |= J9_STACKWALK_SKIP_HIDDEN_FRAMES;
98
}
99
walkState->frameWalkFunction = stackFrameFilter;
100
const char * walkerMethodChars = env->GetStringUTFChars(stackWalkerMethod, NULL);
101
if (NULL == walkerMethodChars) { /* native out of memory exception pending */
102
return NULL;
103
}
104
walkState->userData2 = (void *) walkerMethodChars;
105
UDATA walkStateResult = vm->walkStackFrames(vmThread, walkState);
106
Assert_JCL_true(walkStateResult == J9_STACKWALK_RC_NONE);
107
walkState->flags |= J9_STACKWALK_RESUME;
108
walkState->userData1 = (void *)(UDATA)flags;
109
if (J9SF_FRAME_TYPE_END_OF_STACK != walkState->pc) {
110
/* indicate the we have the topmost client method's frame */
111
walkState->userData1 = (void *)((UDATA) walkState->userData1 | FRAME_VALID);
112
}
113
114
jmethodID walkImplMID = JCL_CACHE_GET(env, MID_java_lang_StackWalker_walkWrapperImpl);
115
if (NULL == walkImplMID) {
116
walkImplMID = env->GetStaticMethodID( clazz, "walkImpl", "(Ljava/util/function/Function;J)Ljava/lang/Object;");
117
Assert_JCL_notNull (walkImplMID);
118
JCL_CACHE_SET(env, MID_java_lang_StackWalker_walkWrapperImpl, walkImplMID);
119
}
120
jobject result = env->CallStaticObjectMethod(clazz, walkImplMID, function, (jlong)(UDATA)walkState);
121
122
if (NULL != walkerMethodChars) {
123
env->ReleaseStringUTFChars(stackWalkerMethod, walkerMethodChars);
124
}
125
vmThread->stackWalkState = newWalkState.previous;
126
127
return result;
128
}
129
130
jobject JNICALL
131
Java_java_lang_StackWalker_getImpl(JNIEnv *env, jobject clazz, jlong walkStateP)
132
{
133
J9VMThread *vmThread = (J9VMThread *) env;
134
J9JavaVM *vm = vmThread->javaVM;
135
J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;
136
J9MemoryManagerFunctions const * const mmFuncs = vm->memoryManagerFunctions;
137
J9StackWalkState *walkState = (J9StackWalkState *) ((UDATA) walkStateP);
138
jobject result = NULL;
139
140
enterVMFromJNI(vmThread);
141
142
if (J9_ARE_NO_BITS_SET((UDATA) (walkState->userData1), FRAME_VALID)) {
143
/* skip over the current frame */
144
walkState->userData1 = (void *) ((UDATA)walkState->userData1 & FRAME_FILTER_MASK);
145
if (J9_STACKWALK_RC_NONE != vm->walkStackFrames(vmThread, walkState)) {
146
vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);
147
goto _done;
148
}
149
}
150
/* clear the valid bit */
151
walkState->userData1 = (void *) (((UDATA) walkState->userData1 & FRAME_FILTER_MASK));
152
153
if (J9SF_FRAME_TYPE_END_OF_STACK != walkState->pc) {
154
J9Class * frameClass = J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_OR_NULL(vm);
155
j9object_t frame = mmFuncs->J9AllocateObject(vmThread, frameClass, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
156
if (NULL == frame) {
157
vmFuncs->setHeapOutOfMemoryError(vmThread);
158
} else {
159
J9ROMMethod *romMethod = getOriginalROMMethod(walkState->method);
160
J9Class *ramClass = J9_CLASS_FROM_METHOD(walkState->method);
161
J9ROMClass *romClass = ramClass->romClass;
162
J9ClassLoader* classLoader = ramClass->classLoader;
163
164
result = vmFuncs->j9jni_createLocalRef(env, frame);
165
UDATA bytecodeOffset = walkState->bytecodePCOffset; /* need this for StackFrame */
166
UDATA lineNumber = getLineNumberForROMClassFromROMMethod(vm, romMethod, romClass, classLoader, bytecodeOffset);
167
PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, frame);
168
169
/* set the class object if requested */
170
if (J9_ARE_ANY_BITS_SET((UDATA) walkState->userData1, RETAIN_CLASS_REFERENCE)) {
171
j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(ramClass);
172
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_DECLARINGCLASS(vmThread, frame, classObject);
173
}
174
175
/* set bytecode index */
176
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_BYTECODEINDEX(vmThread, frame, (U_32) bytecodeOffset);
177
178
/* Fill in line number - Java wants -2 for natives, -1 for no line number (which will be 0 coming in from the iterator) */
179
180
if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccNative)) {
181
lineNumber = -2;
182
} else if (lineNumber == 0) {
183
lineNumber = -1;
184
}
185
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_LINENUMBER(vmThread, frame, (I_32) lineNumber);
186
187
j9object_t stringObject = J9VMJAVALANGCLASSLOADER_CLASSLOADERNAME(vmThread, classLoader->classLoaderObject);
188
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CLASSLOADERNAME(vmThread, frame, stringObject);
189
190
J9Module *module = ramClass->module;
191
if (NULL != module) {
192
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_FRAMEMODULE(vmThread, frame, module->moduleObject);
193
}
194
195
stringObject = VM_VMHelpers::getClassNameString(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass), JNI_TRUE);
196
if (VM_VMHelpers::exceptionPending(vmThread)) {
197
goto _pop_frame;
198
}
199
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CLASSNAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);
200
201
stringObject = mmFuncs->j9gc_createJavaLangStringWithUTFCache(vmThread, J9ROMMETHOD_NAME(romMethod));
202
if (VM_VMHelpers::exceptionPending(vmThread)) {
203
goto _pop_frame;
204
}
205
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_METHODNAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);
206
207
stringObject = mmFuncs->j9gc_createJavaLangStringWithUTFCache(vmThread, J9ROMMETHOD_SIGNATURE(romMethod));
208
if (VM_VMHelpers::exceptionPending(vmThread)) {
209
goto _pop_frame;
210
}
211
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_METHODSIGNATURE(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);
212
213
stringObject = J9VMJAVALANGCLASS_FILENAMESTRING(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass));
214
if (NULL == stringObject) {
215
J9UTF8 *fileName = getSourceFileNameForROMClass(vm, classLoader, romClass);
216
if (NULL != fileName) {
217
stringObject = mmFuncs->j9gc_createJavaLangString(vmThread, J9UTF8_DATA(fileName), J9UTF8_LENGTH(fileName), J9_STR_TENURE);
218
if (VM_VMHelpers::exceptionPending(vmThread)) {
219
goto _pop_frame;
220
}
221
/* Update the cached fileNameString on the class so subsequent calls will find it */
222
J9VMJAVALANGCLASS_SET_FILENAMESTRING(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass), stringObject);
223
}
224
}
225
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_FILENAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);
226
227
if (J9ROMMETHOD_IS_CALLER_SENSITIVE(romMethod)) {
228
J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CALLERSENSITIVE(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), TRUE);
229
}
230
231
_pop_frame:
232
DROP_OBJECT_IN_SPECIAL_FRAME(vmThread);
233
}
234
}
235
_done:
236
exitVMToJNI(vmThread);
237
238
return result;
239
}
240
241
} /* extern "C" */
242
243