2015-12-29 64 views
0

我使用JNI的Android 1.5.1工作室針對Android的API 18,我的問題是調用堆棧Dalvik的:從本地代碼

問題1)如何從本地代碼調用的Dalvik內部的功能呢?

例如在Android source code,在解釋器模塊中,在stack.cpp中,如何從本機代碼調用函數dvmDumpThreadStack(const DebugOutputTarget * target,Thread * thread)?

看來我需要包含一些文件並鏈接到一些庫,如answer中所述,但我需要具體的細節。我需要鏈接哪些文件以及哪些文件需要包含在我的本機代碼中才能成功調用dvmDumpThreadStack函數?

這是Andorid.md的內容文件

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) 

問題2)如何與所需的值定義所需的參數調用的Dalvik內部的功能呢?例如,在我調用dvmDumpThreadStack函數之前,如何在調用函數之前定義目標和線程,以及在它們中存儲哪些值。

回答

1

一般來說,你沒有。出於某種原因,他們被稱爲「內部」功能。

如果您真的確定要這樣做,您可以使用dlsym()在運行時查找地址來查找函數指針。您需要使用「mangled」名稱,您可以通過使用nm檢查二進制文件來獲得該名稱。 (在代碼從C切換到C++之前,在4.1或更早的版本中,這很容易)。您可以通過調用Thread.cpp中的dvmGetThread函數(dvmGetThreadByHandle,dvmGetThreadByThreadIddvmGetThreadFromThreadObject),或者如果您對當前線程感興趣,可致電dvmThreadSelf()。將它傳遞給dvmDumpThread(),這將設置DebugOutputTarget,因此您不必這樣做。

您不需要定義線程*來傳遞線程*的頭文件。只需將線程獲取函數聲明爲返回void *,並將線程轉儲函數聲明爲接受void *參數。如果您擔心類型安全性和可移植性,請不要通過應用程序調用內部VM功能。

有一次我真的想這樣做 - 調試一些東西,不記得是什麼 - 我實際上給不帶參數的VM添加了一個新的extern "C"函數,只是拋棄了當前線程的堆棧。這使得一切都變得容易了。

+0

你的意思是這樣調用: dvmDumpThreadStack(dvmDumpThread(dvmThreadSelf(),FALSE),dvmThreadSelf()),但使用dlsym()來獲取函數指針 – User

+0

同樣的dlsym()需要一個文件句柄對象文件。並找到Dalvik Stack.o目標文件的句柄似乎不起作用: handle = dlopen(「Stack.o」,RTLD_NOW); func =(void(*)())dlsym(handle,「dvmDumpThreadStack」); – User

+0

檢查'dlsym()'的手冊頁,特別是關於兩個「僞手柄」。 C++對象使用「mangled」名稱,因此對於C++源代碼,符號不會簡單地爲「dvmDumpThreadStack」。使用帶有-D標誌的NDK中的'nm'命令(android-eabi-nm或類似的東西)掃描dalvik .so作爲符號名稱。您可以使用'C++ filt'來取消您發現的名稱,以確認您擁有正確的東西。 – fadden