- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
虽然也有类似的问题(比如 1 , 2 , 3 ),但是他们的回答并没有解决我的问题。
我正在使用 Android NDK 和 Android Studio 1.5.1,目标是 Android API 18(在 Android KitKat 4.4 之前,所以我处理的是 Dalvik,而不是 ART 运行时)。
我知道原始 Java 局部变量应该在 Dalvik 解释器堆栈上,但我找不到它。
我使用以下代码在 Java 代码中声明了一个 Java 本地整数魔数(Magic Number) (0x23420023) 并使用 native 代码(C 代码)搜索它。
我将 Java 代码的进程 ID (pid) 和线程 ID (tid) 传递给 C 代码,因此我可以搜索声明该魔数(Magic Number)变量的 Java 方法占用的虚拟地址空间。
在 C 代码中,我通过读取和解析文件/proc/pid/task/tid/maps 来获取 Java 代码的内存区域
问题是什么?
当我扫描内存区域时(从文件/proc/pid/task/tid/maps 中提取):
ad5b1000-ad7d7000 r--p 00000000 1f:01 756/data/dalvik-cache/data@app@com.example.magicnumber2-1.apk@classes.dex
我可以立即找到魔数(Magic Number),但问题是内存区域被应用程序目标文件占用,而不是 Dalvik 堆栈。您可以通过取消注释标记为“//1-dex:”的第一个 if 语句并注释掉标记为“//2-permission:”和“//3-inode”的第二个和第三个 if 语句来确认这一点C 代码中的两个 while 循环。
但是,当我搜索其他剩余的内存区域(从文件/proc/pid/task/tid/maps 中提取)时,它们具有读取、写入和私有(private)权限“rw-p”(因为 Dalvik 堆栈应该具有读/写/私有(private)权限),我收到段错误。您可以通过注释掉标记为“//1-dex:”的第一个 if 语句并取消注释标记为“//2-permission:”和“//3-inode”的第二个和第三个 if 语句来确认这一点C 代码中的两个 while 循环。
Java代码:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("MyLibrary");
}
public native boolean findMagicNumber(int pid, int tid);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int magicNumber = 0x23420023 ;
int pid = android.os.Process.myPid();
int tid = android.os.Process.myTid();
findMagicNumber(pid, tid);
System.out.println("********** magicNumber = " + magicNumber + " PID=" + pid + " TID=" + tid);
}
}
C代码:
#include "com_example_magicnumber2_MainActivity.h"
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {
long long startaddr, endaddr, size, offset, inode;
char permissions[8], device[8], filename[200], line[250];
char *start, *end, *candidate;
char filepath[100];
//pid is the process id and tid is the thread id of the Java calling method from the Java code
sprintf(filepath,"/proc/%d/task/%d/maps", pid, tid);
FILE* file = fopen(filepath, "r");
while (fgets(line, sizeof(line), file)) {
memset( filename, '\0', sizeof(filename) );
sscanf(line,"%llx-%llx %s %llx %s %llx %s", &startaddr, &endaddr, permissions, &offset, device, &inode, filename);
//1-dex: examine only the memory region mapped to the app dex file
if ((strstr(filename,".dex"))==NULL) continue;
//2-permission: examine only read, write, and private memory regions
//if (((strstr(permissions, "rw-p")))==NULL) continue;
//3-inode: examine only the memory region that is not mapped to a file or device
//if (inode !=0) continue;
__android_log_print(ANDROID_LOG_DEBUG,":", "%llx-%llx %s %llx %s %llx %s",
startaddr, endaddr, permissions, offset, device, inode, filename);
start = startaddr;
end = endaddr;
candidate = memchr( start, 0x14, (end-start));
while( candidate !=0){
if ((candidate[2]== 0x23) &&
(candidate[3] == 0x00) &&
(candidate[4] == 0x42) &&
(candidate[5] == 0x23)){
__android_log_print(ANDROID_LOG_DEBUG,"@@@@@@@@@@","The magic number is found at %p", candidate);
break;
}
else
candidate = memchr(candidate+1, 0x14, (end-candidate));
}
}
}
最佳答案
JNI 提供了一种访问 native 代码中的 java 变量的机制,此处对此进行了描述:http://www.math.uni-hamburg.de/doc/java/tutorial/native1.1/implementing/field.html
然后你可以使用
&x; // gets the address of x
获取变量的地址
另一种方法是使用汇编程序,即下面的代码打印堆栈的开始(通过打印堆栈指针和基指针的地址)
#include <stdio.h>
unsigned long get_sp(){
__asm__("mov %rsp, %rax ");
}
unsigned long get_bp(){
__asm__("mov %rbp, %rax ");
}
int main(int argc, char **argv)
{
int n;
printf("SP 0x%x\n", get_sp());
printf("BP 0x%x\n", get_bp());
return 0;
}
关于java - 如何使用 native 代码以编程方式查找 Java 局部变量的内存地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34626536/
有人可以解释一下为什么我得到: "use of unassigned local variable number_of_column" for: if (i f.LastWriteTime).Fir
我正在尝试为查询定义和初始化 MySQL 变量。 我有以下几点: declare @countTotal int; SET @countTotal = select COUNT(*) from nG
局部变量由小写字母或下划线(_)开头.局部变量不像全局和实变量一样在初始化前含nil值. ruby>$foo nil ruby>@foo nil ruby>foo ER
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
当我单击 Login 类上的注册按钮时,出现 nullpointerException,它给出了该错误。我尝试修改本地和全局变量,但似乎没有任何方法可以修复该错误,我可能在 onClickListen
我之前看过一些关于此的帖子,但我一直无法找到有关 actionListeners 的帖子。我正在尝试使用 JButton 数组创建井字棋。如果可能的话,如何在使用 for 循环临时变量的同时向它们添加
我试图找出一种将 getView() 方法中的位置变量传递给内部类的方法。但是,这不能是最终变量,因为 ListView 中的每个项目都会调用 getView() ,因此它会发生变化。有没有办法访问该
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
这对你们中的某些人来说似乎微不足道,但我对下面的这两个示例感到困惑。 int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int i
这个问题在这里已经有了答案: How do JavaScript closures work? (86 个答案) 关闭 7 年前。 所以我正在复习我的 vanilla Javascript,专门用于
我正在将mockito与spring(java 1.8)一起使用,并且我尝试在我的Answer对象中使用局部变量: public IProductDTO productForMock = null;
是否可以在java中为静态方法注入(inject)局部变量,比如 @Inject public void someMethod() { @MyInjectQualifier MyObjectC
我有一个函数,每 2 秒被重复调用一次,每次从屏幕顶部带来一个具有随机纹理的球。我希望能够在 touchesBegan 中使用这个球,但我不能,因为它是一个局部变量。我试过将它设为全局变量,但这给了我
这是(我假设)一个基本问题,但我似乎无法弄清楚。 给定以下代码: from src.Globals import * import pygame # Used to manage how fast t
这就是我在循环中引用全局变量的方法。 _.forEach(myTableName.detailsObjects, function (o, key) { if
我已经创建了一些代码: import numpy as np Length=(2.7)*10**-3 Nx=4 x = np.linspace(0, Length, Nx+1) # mes
如何获取局部变量? 我有这个代码 if (ctrl is Control) { Control c = (Control)ctrl; foreach (object innerCtrl
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Difference between class variables and class instance
我正在学习 Python 3,我有一个关于 Python 中面向对象编程的非常基本的问题。这是我的代码。 class pet: number_of_legs = 0 def count
我有以下代码块: class Student{ int age; //instance variable String name; //instance varia
我是一名优秀的程序员,十分优秀!