
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
掌握不同的软件编程开发知识能够让软件开发程序员适应不同的编程开发场景,而本文我们就通过案例分析来简单了解一下,JNIEnv线程问题都有哪些。
JNIEnv的线程限制
一个JNIEnv指针仅在其相关联的线程中有效。你不能将这个指针从一个线程中传递给另一个线程,或者在多线程中缓存和使用它。Java虚拟机在同一个线程的连续调用中传递给本地方法相同的JNIEnv指针,但是从不同线程中调用本地方法时传递的是不同的JNIEnv指针。应当避免缓存一个线程的JNIEnv指针并在另一个线程中使用指针的常见错误。
本地引用(局部引用)仅在创建它的线程中有效。你不能将本地引用从一个线程中传递到另一个线程。每当有多个线程可能使用相同引用的可能性时,应始终将本地引用转换为全局引用。
JNIEnv是用作线程局部存储。因此,使用者不能在多线程间共享一个JNIEnv变量。如果在一段代码中没有其它办法获得它的JNIEnv,使用者可以共享JavaVM对象,使用GetEnv来取得该线程下的JNIEnv。
如果你使用AttachCurrentThread连接(attach)了Native进程,正在运行的代码在线程分离(detach)之前绝不会自动释放局部引用。使用者创建的任何局部引用必须手动删除。通常,任何在循环中创建局部引用的Native代码可能都需要做一些手动删除。
全局获取JNIEnv
一个JNIEnv指针仅在与其相关联的线程中有效。对于本地方法,这通常不是问题,因为他们从虚拟机接受JNIEnv指针作为一个参数。然而有时候可能不需要直接从虚拟机调用的本地代码来获取属于当前线程的JNIEnv接口指针。例如通过JNI在Native开启了一个子线程处理某些任务,在这些任务处理完毕后需要将处理结果回调给java层。
不要混淆ID和引用
JNI将对象作为引用。类,字符串和数组是特殊类型的引用。JNI将方法和字段作为ID。一个ID不是一个参考。不要将类引用称为“类ID”,也不要将方法ID称为“方法引用”。
引用是可以由本地代码显式管理的虚拟机资源。例如,JNI函数DeleteLocalRef允许本地代码删除本地引用。相比之下,字段和方法ID由虚拟机管理并保持有效直到其定义的类被卸载。在虚拟机卸载定义的类之前,本机代码不能显式删除字段或方法ID。
缓存字段和方法ID
本地代码通过将字段或方法的名称和类型描述符指定为字符串然后从虚拟机获取字段或方法ID。使用名称和类型字符串的字段和方法查找速度很慢。缓存这些ID通常是有利的,未能缓存字段和方法ID是本机代码中的常见性能问题。
缓存字段或方法ID建议使用类的静态代码块的方式进行缓存。
避免过量创建本地引用
虽然说本地引用会在函数结束时自动释放,但是JNI对于本地引用的个数是有一定的限制的,一般是限制到512个,因此需要注意一些调用链比较长的函数或者是在循环体内返回的本地引用在使用完毕后及时进行释放,以保证GC的正常工作和内存的稳定。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。