我正在尝试创建一个新线程,因此我将 VM 从我的方法初始化(从 Java 调用)传递到我的新线程。在线程中,我调用 AttachCurrentThread 并获取 JNIEnv* env。
稍后,我尝试使用环境调用 GetObjectClass,但它崩溃了。我相信这是因为对象可能未初始化,但我正在尝试调用在包含 native 方法的类中定义的方法。我一直在尝试遵循 http://java.sun.com/docs/books/jni/html/fldmeth.html 的第 4.2 节(开头) .
非常奇怪的事情:我正在使用运行 2.2 的 HTC Dream 进行测试并且以下代码不会崩溃,但是使用运行 2.2.2 的摩托罗拉 Droid 时它会一直崩溃!
这是我的代码:
C++
JNIEXPORT void JNICALL Java_com_device_client_HostConnection_initialize
(JNIEnv * env, jobject obj, jint port) {
JavaVM *vm;
jint result = env->GetJavaVM(&vm);
if (result < 0) {
LOGE("Error using GetJavaVM\n");
exit(-1);
}
struct javaInfo* data = (struct javaInfo*) malloc(sizeof(struct javaInfo));
data->vm = vm;
data->javaObjHost = obj;
pthread_t pth;
pthread_create(&pth, NULL, startServer, (void *) data);
}
新线程:
void *startServer(void* arg) {
jclass cls;
jmethodID mid;
JNIEnv* env = NULL;
struct javaInfo* data = (struct javaInfo*) arg;
JavaVM* vm = data->vm;
jobject javaObjHost = data->javaObjHost;
if (vm == NULL) {
LOGE("VM is null\n");
}
vm->AttachCurrentThread(&env, NULL);
cls = env->GetObjectClass(javaObjHost);
mid = env->GetMethodID(cls, "setStatus", "(Z)V");
if (mid == 0) {
LOGD("ERROR: GetMethodID\n");
exit(-1);
}
env->CallVoidMethod(javaObjHost, mid, false);
行 cls = env->GetObjectClass(javaObjHost);正在崩溃并显示以下输出:
W/dalvikvm( 5827): JNI WARNING: 0x44872da0 is not a valid JNI reference
W/dalvikvm( 5827): in Ldalvik/system/NativeStart;.run ()V (GetObjectClass)
I/dalvikvm( 5827): "Thread-9" prio=5 tid=8 RUNNABLE
I/dalvikvm( 5827): | group="main" sCount=0 dsCount=0 s=N obj=0x448734c8 self=0x229da8
I/dalvikvm( 5827): | sysTid=5834 nice=0 sched=0/0 cgrp=default handle=2265136
I/dalvikvm( 5827): | schedstat=( 885010 3631591 2 )
I/dalvikvm( 5827): at dalvik.system.NativeStart.run(Native Method)
I/dalvikvm( 5827):
E/dalvikvm( 5827): VM aborting
I/DEBUG ( 5511): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 5511): Build fingerprint: 'verizon/voles/sholes/sholes:2.2.2/FRG83G/91102:user/release-keys'
I/DEBUG ( 5511): pid: 5827, tid: 5834 >>> com.device.client <<<
I/DEBUG ( 5511): signal 11 (SIGSEGV), fault addr deadd00d
....
我的java代码:
public class HostConnection {
static {
System.loadLibrary("hostConnection");
}
public void setStatus(boolean bool) {
...
}
public native void initialize(int defaultPort);
}
谁能帮帮我?我想在我的类中调用 setStatus() 方法,而不创建新对象。
编辑:
这是新代码,目前正在崩溃。
JNIEXPORT void JNICALL Java_com_device_client_HostConnection_initialize
(JNIEnv * env, jobject obj, jint port) {
JavaVM *vm;
jint result = env->GetJavaVM(&vm);
if (result < 0) {
LOGE("Error using GetJavaVM\n");
exit(-1);
}
jclass clsLocal = env->GetObjectClass(obj);
if (clsLocal == NULL) {
LOGE("ERROR: Cannot find class HostConnection\n");
exit(-1);
}
jclass hostClass = (jclass) env->NewWeakGlobalRef(clsLocal);
if (hostClass == NULL) {
LOGE("ERROR: Run out of memory for weak global ref\n");
exit(-1);
}
struct javaInfo* data = (struct javaInfo*) malloc(sizeof(struct javaInfo));
data->vm = vm;
data->hostClass = hostClass;
pthread_t pth;
pthread_create(&pth, NULL, startServer, (void *) data);
}
void *startServer(void* arg) {
JNIEnv* env = NULL;
jmethodID mid;
struct fb_var_screeninfo vinfo;
char server[MAXHOSTNAMELEN];
struct javaInfo* data = (struct javaInfo*) arg;
JavaVM* vm = data->vm;
jclass hostClass = data->hostClass;
if (vm == NULL) {
LOGE("VM is null\n");
}
vm->AttachCurrentThread(&env, NULL);
mid = env->GetMethodID(hostClass, "setStatus", "(Z)V");
if (mid == 0) {
LOGD("ERROR: GetMethodID\n");
exit(-1);
}
env->CallVoidMethod(hostClass, mid, false);
}
我遇到以下崩溃:
W/dalvikvm( 7650): JNI WARNING: jclass points to invalid object 0xda88d23f
I/dalvikvm( 7650): "Thread-9" prio=5 tid=8 NATIVE
I/dalvikvm( 7650): | group="main" sCount=0 dsCount=0 s=N obj=0x448734f8 self=0x228a20
I/dalvikvm( 7650): | sysTid=7657 nice=0 sched=0/0 cgrp=default handle=2260192
I/dalvikvm( 7650): | schedstat=( 854493 9155273 2 )
I/dalvikvm( 7650): at dalvik.system.NativeStart.run(Native Method)
I/dalvikvm( 7650):
E/dalvikvm( 7650): VM aborting
I/DEBUG ( 5511): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 5511): Build fingerprint: 'verizon/voles/sholes/sholes:2.2.2/FRG83G/91102:user/release-keys'
I/DEBUG ( 5511): pid: 7650, tid: 7657 >>> com.device.client <<<
I/DEBUG ( 5511): signal 11 (SIGSEGV), fault addr deadd00d
我知道它在 GetMethodID() 上崩溃。我真的不知道为什么。非常感谢任何帮助。
非常感谢。
最佳答案
您从Java_com_device_client_HostConnection_initialize 获取对象 作为本地引用,然后将其传递给javaInfo 结构中的新线程。
局部引用只在当前线程有效,与JNIEnv*指针一样。
因此,当您从新线程中的结构中获取它时,您对该对象的引用无效,这就解释了崩溃。
尝试使用 JNIEnv 中的 NewWeakGlobalRef 方法在 Java_com_device_client_HostConnection_initialize 方法中获取 WeakGlobal 引用。
阅读 JNI 文档的第五章以了解本地、全局和弱全局引用之间的区别。
关于安卓 JNI : GetObjectClass crashes with SIGSEGV (not a valid JNI reference),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7864614/
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
快捷目录前言一、涉及到的相关技术简介二、具体实现过程及踩坑杂谈1.安卓手机改造成linux系统实现方案2.改造后的手机Linux中软件的安装3.手机Linux中安装MySQL5.7踩坑实录4.手机Linux中安装软件的正确方法三、Linux服务器部署前后端分离项目流程1.前提准备(安装必要软件,搭建环境):2.前后端分离项目的详细部署过程:总结前言总体概述:本篇文章隶属于“手机改造服务器部署前后端分离项目”系列专栏,该专栏将分多个板块,每个板块独立成篇来详细记录:手机(安卓)改造成个人服务器(Linux)、Linux中安装软件、配置开发环境、部署JAVA+VUE+MySQL5.7前后端分离项目
在微信小程序开发中遇到在video组件的两个问题1.安卓手机里播放视频会有明显的卡顿问题刚开始以为是网络问题,或者是视频文件问题。排查了一下发现都没问题最后加了个属性就OK了uniapp和原生小程序方法:custom-cache="false"custom-cache={{false}}video组件兼容iOS手机custom-cache加了这个属性会让2.iOS手机第一次播放视频会有几秒黑屏问题因此我加了当前手机型号的判断uni.getDeviceInfo().deviceType获取当前设备api当为iPhone时不加custom-cache属性,否则加上custom-cache=“fal
安卓渐变的背景框实现1.背景实现方法1.利用PorterDuffXfermode进行图层的混合,这是最推荐的方法,也是最有效的。2.利用canvas裁剪实现,这个方法有个缺陷,就是圆角会出现毛边,也就是锯齿。3.利用layer绘制边框1.背景万恶的设计小姐姐又来搞事情啦,你说好好的设计一个纯色的背景框框不好嘛,非要把一个框框弄成渐变的,如果不拿出放大镜估计没几个人能看出来它是渐变的。来,我让你看看是啥样框子是从左到右渐变的,设计应该是做了一个底图,然后上面盖了一个白色圆角矩形。那么我们该怎么去实现它呢?实现方法下面介绍三种实现它的方法。先贴上源码地址,大家记得给个starhttps://git
简介:有时我们需要调试手机浏览器网页信息,这时除了使用fiddler抓包拦截篡改,还可以通过USB连接,通过PC远程调试手机上的浏览器信息,进行映射。历史攻略:adb:安卓手机USB调试模式前置准备:网页内容在移动设备上的体验可能和电脑上完全不同。ChromeDevTools提供远程调试功能安卓远程调试支持:在浏览器选项卡中调试网站。在原生安卓应用中调试网页内容。将屏幕从你的安卓设备上投影到你的开发机器上。使用端口转发和虚拟主机映射来让安卓设备访问开发使用的服务器。操作步骤:1、手机通过USB连接电脑。2、开启手机调试模式。3、PC电脑edge输入:edge://inspect/#device
Java对象生命周期:创建:为对象分配内存空间,构造对象应用:此时对象至少被一个强引用持有不可见:未被任何强引用持有,进行可达性分析不可达:可达性分析为不可达,进入下一阶段收集:当垃圾回收器发现该对象已经处于“不可达阶段”并且垃圾回收器已经对该对象的内存空间重新分配做好准备时,则对象进入了“收集阶段”。如果该对象已经重写了finalize()方法,则会去执行该方法的终端操作。终结:当对象执行完finalize()方法后仍然处于不可达状态时(可达性分析垃圾回收算法被回收前,会有两次标记过程,判断是否执行lfinalize()方法,执行完之后判断是否GCROOT可达,如果仍不可达,则准备回收),则
最近换了工作,新工作是负责用qml做qt安卓开发。工作中遇到一个问题:安卓设备有USB口,需要插入一个U盘在程序里读写U盘中的文件,由于安卓系统的安全性的问题导致QFile、c++的文件操作相关方法都不能读写成功,想要读写成功只能调用java代码,在java代码里面使用安卓的DocumentFile库。经过一番探索,成功解决了问题。qt如何添加java代码不说了,网上有。下面是具体的java代码:packagecom.example.myapplication;importandroid.annotation.TargetApi;importandroid.content.Context;im
Obsidian安卓端同步及使用(RemotelySave+阿里云同步S3)强烈推荐的obsidian的markdown教程obsidian这款软件很不错,最近刚入门,用来做笔记,喜欢在电脑上做笔记,手机端能随时查看,故捣鼓了一下安卓端的同步及安卓端的使用1.安装包获取不能科学上网,我是到官方中文论坛上找到的,网址如下:移动端v1.4.1开始测试-Obsidian中文论坛2.电脑端同步+阿里云配置我使用的是RemotelySave插件首先,电脑端关闭安全模式,下载这个第三方插件,登不上的看这里,网址如下:完美解决obsidian无法加载第三方插件(社区插件)的问题然后就是阿里云的同步
我知道这里有一百个问题和我一样,但似乎没有一个适合我的具体问题,所以我要问一个新问题。以防万一这是重复,我很抱歉。所以,我正在构建一个应用程序,布局给我带来了一些问题。这是我的XML代码:(尚未完成)我得到的错误是在代码的第一行它说“错误:在包'android'中找不到属性'xmlns'的资源标识符我一遍又一遍地检查代码,尝试刷新/重建项目,尝试删除该特定行等等,但似乎没有任何解决办法。那么,如果有人有一些想法?谢谢! 最佳答案 删除android:xmlns="http://schemas.android.com/apk/res/
我正在关注googleAndroidStudio第一个android应用程序教程。但是当我尝试向我的应用程序添加搜索栏时,我现在收到3个奇怪的错误。我现在就在这里,我按照教程添加了XML代码。http://developer.android.com/training/basics/actionbar/adding-buttons.html我得到的错误:Error:(5,23)Noresourcefoundthatmatchesthegivenname(at'icon'withvalue'@drawable/ic_action_search').Error:(6,24)Noresourc