Search code examples
androidnativedalvik

Calling Dalvik Stack from native code


I am using JNI with Android Studio 1.5.1 targeting Android API 18 and my questions are:

Q.1) How can I call Dalvik internal functions from native code?

For example in the Android source code, in the interpreter module, in the stack.cpp, how can I call the function dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) from native code?

It seems that I need to include some files and link to some libraries as stated in this answer but I need specific details. Which files do I need to link to and which files do I need to include in my native code to successfully call the dvmDumpThreadStack function for example?

This is the content of the Andorid.md file

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyLibrary
LOCAL_SRC_FILES := MyLibrary.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)

Q.2) How to define the required arguments with the required values to call Dalvik internal functions? For example, before I call the dvmDumpThreadStack function, how to define target and thread and which values to store in them before I call the function.


Solution

  • Generally speaking, you don't. They're called "internal" functions for a reason.

    If you're really determined to do this, you can find the function pointers by using dlsym() to find the address at runtime. You'll need the "mangled" name, which you can get by examining the binary with nm. (This was easier before the code was switched from C to C++ back in 4.1 or thereabouts.) You can get the Thread* the same way the VM does it, by calling one of the dvmGetThread functions in Thread.cpp (dvmGetThreadByHandle, dvmGetThreadByThreadId, dvmGetThreadFromThreadObject), or by calling dvmThreadSelf() if you're interested in the current thread. Pass that to dvmDumpThread(), which will set up the DebugOutputTarget so you don't have to.

    You don't need a header file that defines Thread* to pass a Thread* around. Just declare the thread-getter functions as returning void*, and the thread-dump function as accepting a void* argument. If you're worried about type-safety and portability, don't call internal VM functions from an app.

    The one time I actually wanted to do this -- debugging something, don't remember what -- I actually added a new extern "C" function to the VM that took no arguments and just dumped the current thread's stack. That made everything much easier.