Path: blob/master/runtime/jcl/common/java_lang_StackWalker.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2017, 2022 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "jni.h"23#include "jcl.h"24#include "jclglob.h"25#include "jclprots.h"26#include "jcl_internal.h"27#include "objhelp.h"28#include "rommeth.h"29#include "vmaccess.h"30#include "VMHelpers.hpp"3132extern "C" {33#define RETAIN_CLASS_REFERENCE 134#define SHOW_REFLECT_FRAMES 235#define SHOW_HIDDEN_FRAMES 436#define FRAME_VALID 837#define FRAME_FILTER_MASK (RETAIN_CLASS_REFERENCE | SHOW_REFLECT_FRAMES | SHOW_HIDDEN_FRAMES)3839static UDATA stackFrameFilter(J9VMThread * currentThread, J9StackWalkState * walkState);4041static UDATA42stackFrameFilter(J9VMThread * currentThread, J9StackWalkState * walkState)43{44/*45* userData1 contains filtering flags, i.e. show hidden, show reflect.46* userData2 contains stackWalkerMethod, the method name to search for47*/48UDATA result = J9_STACKWALK_STOP_ITERATING;4950if (NULL != walkState->userData2) { /* look for stackWalkerMethod */51J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method);52J9ROMClass *romClass = J9_CLASS_FROM_METHOD(walkState->method)->romClass;5354J9UTF8 *utf = J9ROMMETHOD_NAME(romMethod);55const char *stackWalkerMethod = (const char *) walkState->userData2;56result = J9_STACKWALK_KEEP_ITERATING;5758if (compareUTF8Length(J9UTF8_DATA(utf), J9UTF8_LENGTH(utf), (void *) stackWalkerMethod, strlen(stackWalkerMethod)) == 0) {59utf = J9ROMCLASS_CLASSNAME(romClass);60if (J9UTF8_LITERAL_EQUALS(J9UTF8_DATA(utf), J9UTF8_LENGTH(utf), "java/lang/StackWalker")) {61walkState->userData2 = NULL; /* Iteration will skip hidden frames and stop at the true caller of stackWalkerMethod. */62}63}64} else if (J9_ARE_NO_BITS_SET((UDATA) (walkState->userData1), SHOW_REFLECT_FRAMES | SHOW_HIDDEN_FRAMES)65&& VM_VMHelpers::isReflectionMethod(currentThread, walkState->method)66) {67/* skip reflection/MethodHandleInvoke frames */68result = J9_STACKWALK_KEEP_ITERATING;69} else {70result = J9_STACKWALK_STOP_ITERATING;71}7273return result;74}7576jobject JNICALL77Java_java_lang_StackWalker_walkWrapperImpl(JNIEnv *env, jclass clazz, jint flags, jstring stackWalkerMethod, jobject function)78{79J9VMThread *vmThread = (J9VMThread *) env;80J9JavaVM *vm = vmThread->javaVM;8182J9StackWalkState newWalkState;83J9StackWalkState *walkState = vmThread->stackWalkState;8485Assert_JCL_notNull (stackWalkerMethod);86memset(&newWalkState, 0, sizeof(J9StackWalkState));87newWalkState.previous = walkState;88vmThread->stackWalkState = &newWalkState;89walkState->walkThread = vmThread;90walkState->flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_WALK_TRANSLATE_PC91| J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY;92/* If -XX:+ShowHiddenFrames and StackWalker.SHOW_HIDDEN_FRAMES option has not been set, skip hidden method frames */93if (J9_ARE_NO_BITS_SET(vm->runtimeFlags, J9_RUNTIME_SHOW_HIDDEN_FRAMES)94&& J9_ARE_NO_BITS_SET((UDATA)flags, SHOW_HIDDEN_FRAMES)95) {96walkState->flags |= J9_STACKWALK_SKIP_HIDDEN_FRAMES;97}98walkState->frameWalkFunction = stackFrameFilter;99const char * walkerMethodChars = env->GetStringUTFChars(stackWalkerMethod, NULL);100if (NULL == walkerMethodChars) { /* native out of memory exception pending */101return NULL;102}103walkState->userData2 = (void *) walkerMethodChars;104UDATA walkStateResult = vm->walkStackFrames(vmThread, walkState);105Assert_JCL_true(walkStateResult == J9_STACKWALK_RC_NONE);106walkState->flags |= J9_STACKWALK_RESUME;107walkState->userData1 = (void *)(UDATA)flags;108if (J9SF_FRAME_TYPE_END_OF_STACK != walkState->pc) {109/* indicate the we have the topmost client method's frame */110walkState->userData1 = (void *)((UDATA) walkState->userData1 | FRAME_VALID);111}112113jmethodID walkImplMID = JCL_CACHE_GET(env, MID_java_lang_StackWalker_walkWrapperImpl);114if (NULL == walkImplMID) {115walkImplMID = env->GetStaticMethodID( clazz, "walkImpl", "(Ljava/util/function/Function;J)Ljava/lang/Object;");116Assert_JCL_notNull (walkImplMID);117JCL_CACHE_SET(env, MID_java_lang_StackWalker_walkWrapperImpl, walkImplMID);118}119jobject result = env->CallStaticObjectMethod(clazz, walkImplMID, function, (jlong)(UDATA)walkState);120121if (NULL != walkerMethodChars) {122env->ReleaseStringUTFChars(stackWalkerMethod, walkerMethodChars);123}124vmThread->stackWalkState = newWalkState.previous;125126return result;127}128129jobject JNICALL130Java_java_lang_StackWalker_getImpl(JNIEnv *env, jobject clazz, jlong walkStateP)131{132J9VMThread *vmThread = (J9VMThread *) env;133J9JavaVM *vm = vmThread->javaVM;134J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;135J9MemoryManagerFunctions const * const mmFuncs = vm->memoryManagerFunctions;136J9StackWalkState *walkState = (J9StackWalkState *) ((UDATA) walkStateP);137jobject result = NULL;138139enterVMFromJNI(vmThread);140141if (J9_ARE_NO_BITS_SET((UDATA) (walkState->userData1), FRAME_VALID)) {142/* skip over the current frame */143walkState->userData1 = (void *) ((UDATA)walkState->userData1 & FRAME_FILTER_MASK);144if (J9_STACKWALK_RC_NONE != vm->walkStackFrames(vmThread, walkState)) {145vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);146goto _done;147}148}149/* clear the valid bit */150walkState->userData1 = (void *) (((UDATA) walkState->userData1 & FRAME_FILTER_MASK));151152if (J9SF_FRAME_TYPE_END_OF_STACK != walkState->pc) {153J9Class * frameClass = J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_OR_NULL(vm);154j9object_t frame = mmFuncs->J9AllocateObject(vmThread, frameClass, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);155if (NULL == frame) {156vmFuncs->setHeapOutOfMemoryError(vmThread);157} else {158J9ROMMethod *romMethod = getOriginalROMMethod(walkState->method);159J9Class *ramClass = J9_CLASS_FROM_METHOD(walkState->method);160J9ROMClass *romClass = ramClass->romClass;161J9ClassLoader* classLoader = ramClass->classLoader;162163result = vmFuncs->j9jni_createLocalRef(env, frame);164UDATA bytecodeOffset = walkState->bytecodePCOffset; /* need this for StackFrame */165UDATA lineNumber = getLineNumberForROMClassFromROMMethod(vm, romMethod, romClass, classLoader, bytecodeOffset);166PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, frame);167168/* set the class object if requested */169if (J9_ARE_ANY_BITS_SET((UDATA) walkState->userData1, RETAIN_CLASS_REFERENCE)) {170j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(ramClass);171J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_DECLARINGCLASS(vmThread, frame, classObject);172}173174/* set bytecode index */175J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_BYTECODEINDEX(vmThread, frame, (U_32) bytecodeOffset);176177/* Fill in line number - Java wants -2 for natives, -1 for no line number (which will be 0 coming in from the iterator) */178179if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccNative)) {180lineNumber = -2;181} else if (lineNumber == 0) {182lineNumber = -1;183}184J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_LINENUMBER(vmThread, frame, (I_32) lineNumber);185186j9object_t stringObject = J9VMJAVALANGCLASSLOADER_CLASSLOADERNAME(vmThread, classLoader->classLoaderObject);187J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CLASSLOADERNAME(vmThread, frame, stringObject);188189J9Module *module = ramClass->module;190if (NULL != module) {191J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_FRAMEMODULE(vmThread, frame, module->moduleObject);192}193194stringObject = VM_VMHelpers::getClassNameString(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass), JNI_TRUE);195if (VM_VMHelpers::exceptionPending(vmThread)) {196goto _pop_frame;197}198J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CLASSNAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);199200stringObject = mmFuncs->j9gc_createJavaLangStringWithUTFCache(vmThread, J9ROMMETHOD_NAME(romMethod));201if (VM_VMHelpers::exceptionPending(vmThread)) {202goto _pop_frame;203}204J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_METHODNAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);205206stringObject = mmFuncs->j9gc_createJavaLangStringWithUTFCache(vmThread, J9ROMMETHOD_SIGNATURE(romMethod));207if (VM_VMHelpers::exceptionPending(vmThread)) {208goto _pop_frame;209}210J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_METHODSIGNATURE(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);211212stringObject = J9VMJAVALANGCLASS_FILENAMESTRING(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass));213if (NULL == stringObject) {214J9UTF8 *fileName = getSourceFileNameForROMClass(vm, classLoader, romClass);215if (NULL != fileName) {216stringObject = mmFuncs->j9gc_createJavaLangString(vmThread, J9UTF8_DATA(fileName), J9UTF8_LENGTH(fileName), J9_STR_TENURE);217if (VM_VMHelpers::exceptionPending(vmThread)) {218goto _pop_frame;219}220/* Update the cached fileNameString on the class so subsequent calls will find it */221J9VMJAVALANGCLASS_SET_FILENAMESTRING(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(ramClass), stringObject);222}223}224J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_FILENAME(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), stringObject);225226if (J9ROMMETHOD_IS_CALLER_SENSITIVE(romMethod)) {227J9VMJAVALANGSTACKWALKERSTACKFRAMEIMPL_SET_CALLERSENSITIVE(vmThread, PEEK_OBJECT_IN_SPECIAL_FRAME(vmThread, 0), TRUE);228}229230_pop_frame:231DROP_OBJECT_IN_SPECIAL_FRAME(vmThread);232}233}234_done:235exitVMToJNI(vmThread);236237return result;238}239240} /* extern "C" */241242243