当前位置: 首页 > news >正文

沈阳市建网站wordpress产品页面模板下载

沈阳市建网站,wordpress产品页面模板下载,设计机构,微网站对比参考链接#xff1a; Java对象如何存储在内存中 JNI#xff0c;Java Native Interface#xff0c;是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code#xff1b;在 native code 中嵌入 Java 虚拟机调用 Java 的…参考链接 Java对象如何存储在内存中 JNIJava Native Interface是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code在 native code 中嵌入 Java 虚拟机调用 Java 的代码。JNI 编程在软件开发中运用广泛其优势可以归结为以下几点利用 native code 的平台相关性在平台相关的编程中彰显优势。对 native code 的代码重用。native code 底层操作更加高效。然而任何事物都具有两面性JNI 编程也同样如此。程序员在使用 JNI 时应当认识到 JNI 编程中如下的几点弊端扬长避短才可以写出更加完善、高性能的代码从 Java 环境到 native code 的上下文切换耗时、低效。JNI 编程如果操作不当可能引起 Java 虚拟机的崩溃。JNI 编程如果操作不当可能引起内存泄漏。JAVA 中的内存泄漏JAVA 编程中的内存泄漏从泄漏的内存位置角度可以分为两种JVM 中 Java Heap 的内存泄漏JVM 内存中 native memory 的内存泄漏。 局部和全局引用 JNI将实例、数组类型暴露为不透明的引用。native代码从不会直接检查一个不透明的引用指针的上下文而是通过使用JNI函数来访问由不透明的引用所指向的数据结构。因为只处理不透明的引用这样就不需要担心不同的java VM实现而导致的不同的内部对象的布局。然而还是有必要了解一下JNI中不同种类的引用1JNI 支持3中不透明的引用局部引用、全局引用和弱全局引用。2局部和全局引用有着各自不同的生命周期。局部引用能够被自动释放而全局引用和若全局引用在被程序员释放之前是一直有效的。3一个局部或者全局引用使所提及的对象不能被垃圾回收。而弱全局引用则允许提及的对象进行垃圾回收。4不是所有的引用都可以在所有上下文中使用的。例如在一个创建返回引用native方法之后使用一个局部引用这是非法的。 那么到底什么是局部引用什么事全局引用它们有什么不同 局部引用 多数JNI函数都创建局部引用。例如JNI函数NewObject创建一个实例并且返回一个指向该实例的局部引用。 局部引用只在创建它的native方法的动态上下文中有效并且只在native方法的一次调用中有效。所有局部引用只在一个native方法的执行期间有效在该方法返回时它就被回收。 在native方法中使用一个静态变量来保存一个局部引用以便在随后的调用中使用该局部引用这种方式是行不通的。例如以下例子误用了局部引用/* This code is illegal */  jstring   MyNewString(JNIEnv *env, jchar *chars, jint len) { static jclass stringClass NULL; jmethodID cid; jcharArray elemArr; jstring result; if (stringClass NULL) { stringClass (*env)-FindClass(env, java/lang/String); if (stringClass NULL) { return NULL; /* exception thrown */ } } /* It is wrong to use the cached stringClass here, because it may be invalid. */ cid (*env)-GetMethodID(env, stringClass, init, ([C)V); ... elemArr (*env)-NewCharArray(env, len); ... result (*env)-NewObject(env, stringClass, cid, elemArr); (*env)-DeleteLocalRef(env, elemArr); return result; } 这种保存局部引用的方式是不正确的因为FindClass()返回的是对java.lang.String的局部引用。这是因为在native代码从MyNewString返回退出时VM 会释放所有局部引用包括存储在stringClass变量中的指向类对象的引用。这样当再次后继调用MyNewString时可能会访问非法地址导致内存被破坏或者系统崩溃。 局部引用失效有两种方式‘1系统会自动释放局部变量。2程序员可以显示地管理局部引用的生命周期例如调用DeleteLocalRef。 一个局部引用可能在被摧毁之前被传给多个native方法。例如MyNewString中返回一个由NewObject创建的字符串引用它将由NewObject的调用者来决定是否释放该引用。而在以下代码中 JNIEXPORT jstring JNICALL Java_C_f(JNIEnv *env, jobject this) { char *c_str ...pre namecode classcpp ... pre namecode classcppreturn MyNewString(c_str);pre namecode classcpp} 在VM接收到来自Java_C_f的局部引用以后将基础字符串对象传递给ava_C_f的调用者然后摧毁原本由MyNewString中调用的JNI函数NewObject所创建的局部引用。 局部对象只属于创建它们的线程只在该线程中有效。一个线程想要调用另一个线程创建的局部引用是不被允许的。将一个局部引用保存到全局变量中然后在其它线程中使用它这是一种错误的编程。 全局引用 在一个native方法被多次调用之间可以使用一个全局引用跨越它们。一个全局引用可以跨越多个线程并且在被程序员释放之前一致有效。和局部引用一样全局引用保证了所引用的对象不会被垃圾回收。 和局部引用不一样局部变量可以由多数JNI函数创建全局引用只能由一个JNI函数创建NewGlobalRef。下面是一个使用全局引用版本的MyNewString/* This code is OK */  jstring   MyNewString(JNIEnv *env, jchar *chars, jint len) { static jclass stringClass NULL; ... if (stringClass NULL) { jclass localRefCls (*env)-FindClass(env, java/lang/String); if (localRefCls NULL) { return NULL; /* exception thrown */ } /* Create a global reference */ stringClass (*env)-NewGlobalRef(env, localRefCls); /* The local reference is no longer useful */ (*env)-DeleteLocalRef(env, localRefCls); /* Is the global reference created successfully? */ if (stringClass NULL) { return NULL; /* out of memory exception thrown */ } } ... } 弱全局引用 弱全局引用是在java 2 SDK1.2才出现的。它由NewGolableWeakRef函数创建并且被DeleteGloablWeakRef函数摧毁。和全局引用一样它可以跨native方法调用也可以跨越不同线程。但是和全局引用不同的是它不阻止对基础对象的垃圾回收。下面是弱全局引用版的MyNewString JNIEXPORT void JNICALL   Java_mypkg_MyCls_f(JNIEnv *env, jobject self) { static jclass myCls2 NULL; if (myCls2 NULL) { jclass myCls2Local (*env)-FindClass(env, mypkg/MyCls2); if (myCls2Local NULL) { return; /* cant find class */ } myCls2 NewWeakGlobalRef(env, myCls2Local); if (myCls2 NULL) { return; /* out of memory */ } } ... /* use myCls2 */ } 弱全局引用在一个被native代码缓存着的引用不想阻止基础对象被垃圾回收时非常有用。如以上例子mypkg.MyCls.f需要缓存mypkg.MyCls2的引用。而通过将mypkg.MyCls2缓存到弱引用中能够实现MyCls2类依旧可以被卸载。 上面代码中我们假设了MyCls类和MyCls2类的生命周期是相同的例如在同一个类中被加载、卸载。所以没有考虑MyCls2被卸载了然后在类MyCls和native方法的实现Java_mypkg_MyCls_f还要被继续使用时再被重新加载起来的情况。针对于这个MyCls2类可能被卸载再加载的情况在使用时需要检查该弱全局引用是否还有效。如何检查这将在下面提到。 比较引用 可以用JNI函数IsSameObject来检查给定的两个局部引用、全局引用或者弱全局引用是否指向同一个对象。(*env)-IsSameObject(env, obj1, obj2)  返回值为JNI_TRUE表示两个对象一致是同一个对象。JNI_FALSE表示两个对象不一致不是同一个对象。 在java VM中NULL是null的引用。如果一个对象obj是局部引用或者全局引用则可以这样来检查它是否指向null对象 (*env)-IsSameObject(env, obj, NULL) 或者 NULL obj 而对于弱全局引用以上规则需要改变一下我们可以用这个函数来判断一个非0弱全局引用wobj所指向的对象是否仍旧存活着依旧有效。 (*env)-IsSameObject(env, wobj, NULL) 返回值JNI_TRUE表示对象已经被回收了。JNI_FALSE表示wobj指向的对象依旧有效。 释放引用除了引用的对象要占用内存每个JNI引用本身也会消耗一定内存。作为一个JNI程序员应该对在一段给定的时间里程序会用到的引用的个数做到心中有数。特别是尽管程序所创建的局部引用最终会被VM会被自动地释放仍旧需要知道在程序在执行期间的任何时刻创建的局部引用的上限个数。创建过多的引用即便他们是瞬间、短暂的也会导致内存耗尽。 释放局部引用多数情况下在执行一个native方法时你不需要担心局部引用的释放java VM会在native方法返回调用者的时候释放。然而有时候需要JNI程序员显示的释放局部引用来避免过高的内存使用。那么什么时候需要显示的释放呢且看一下情景1在单个native方法调用中创建了大量的局部引用。这可能会导致JNI局部引用表溢出。此时有必要及时地删除那些不再被使用的局部引用。例如以下代码在该循环中每次都有可能创建一个巨大的字符串数组。在每个迭代之后native代码需要显示地释放指向字符串元素的局部引用 for (i 0; i len; i) { jstring jstr (*env)-GetObjectArrayElement(env, arr, i); ... /* process jstr */ (*env)-DeleteLocalRef(env, jstr); } 2你可能要创建一个工具函数它会被未知的上下文调用。例如之前提到到MyNewString这个例子它在每次返回调用者欠都及时地将局部引用释放。 3native方法可能不会返回例如一个可能进入无限事件分发的循环中的方法。此时在循环中释放局部引用是至关重要的这样才能不会无限期地累积进而导致内存泄露。 4native方法可能访问一个巨大的对象因此创建了一个指向该对象的局部引用。native方法在返回调用者之前除访问对象之外还执行了额外的计算。指向这个大对象的局部引用将会包含该对象以防被垃圾回收。这个现象会持续到native方法返回到调用者时即便这个对象不会再被使用也依旧会受保护。在以下例子中由于在lengthyComputation()前显示地调用了DeleteLocalRef所以垃圾回收器有机会可以释放lref所指向的对象。 /* A native method implementation */ JNIEXPORT void JNICALL Java_pkg_Cls_func(JNIEnv *env, jobject this) { lref ... /* a large Java object */ ... /* last use of lref */ (*env)-DeleteLocalRef(env, lref); lengthyComputation(); /* may take some time */ return; /* all local refs are freed */ } 这个情形的实质就是允许程序在native方法执行期间java的垃圾回收机制有机会回收native代码不在访问的对象。 管理局部引用不知道java 7怎么样了应该更强大吧有时间去看看这里且按照java2的特性来吧。SDK1.2中提供了一组额外的函数来管理局部引用的生命周期。他们是EnsureLocalCapacity、NewLocalRef、PushLocalFram以及PopLocalFram。JNI的规范要求VM可以自动确保每个native方法可以创建至少16个局部引用。经验显示如果native方法中未包含和java VM的对象进行复杂的互相操作这个容量对大多数native方法而言已经足够了。如果出现这还不够的情况需要创建更多的局部引用那么native方法可以调用EnsureLocalCapacity来保证这些局部引用有足够的空间。 /* The number of local references to be created is equal to the length of the array. */ if ((*env)-EnsureLocalCapacity(env, len)) 0) { ... /* out of memory */ } for (i 0; i len; i) { jstring jstr (*env)-GetObjectArrayElement(env, arr, i); ... /* process jstr */ /* DeleteLocalRef is no longer necessary */ } 这样做所消耗的内存自然就有可能比之前的版本来的多。 另外PushLocalFram\PopLocalFram函数允许程序员创建嵌套作用域的局部引用。如下代码 #define N_REFS ... /* the maximum number of local references used in each iteration */ for (i 0; i len; i) { if ((*env)-PushLocalFrame(env, N_REFS) 0) { ... /* out of memory */ } jstr (*env)-GetObjectArrayElement(env, arr, i); ... /* process jstr */ (*env)-PopLocalFrame(env, NULL); } PushLocalFram为指定数目的局部引用创建一个新的作用域PopLocalFram摧毁最上层的作用域并且释放该域中的所有局部引用。 使用这两个函数的好处是它们可以管理局部引用的生命周期而不需关系在执行过程中可能被创建的每个单独局部引用。例子中如果处理jstr的过程创建了额外的局部引用它们也会在PopLocalFram之后被立即释放。 NewLocalRef函数在你写一个工具函数时非常有用。这个会在下面章节——管理引用的规则具体分析。 native代码可能会创建超出16个局部引用的范围也可能将他们保存在PushLocalFram或者EnsureLocalCapacity调用VM会为局部引用分配所需要的内存。然而这些内存是否足够是没有保证的。如果内存分配失败虚拟机将会退出。 释放全局引用 在native代码不再需要访问一个全局引用的时候应该调用DeleteGlobalRef来释放它。如果调用这个函数失败Java VM将不会回收对应的对象。 在native代码不在需要访问一个弱全局引用的时候应该调用DeleteWeakGlobalRef来释放它。如果调用这个函数失败了java VM 仍旧将会回收对应的底层对象但是不会回收这个弱引用本身所消耗掉的内存。 管理引用的规则管理引用的目的是为了清除不需要的内存占用和对象保留。 总体来说只有两种类型的native代码直接实现native方法的函数在二进制上下文中被使用的工具函数。 在写native方法的实现的时候需要当心在循环中过度创建局部引用以及在native方法中被创建的却不返回给调用者的局部引用。在native方法方法返回后还留有16个局部引用在使用中将它们交给java VM来释放这是可以接受的。但是native方法的调用不应该引起全局引用和弱全局引用的累积。应为这些引用不会在native方法返后被自动地释放。 在写工具函数的时候必须要注意不能泄露任何局部引用或者超出该函数之外的执行。因为一个工具函数可能在意料之外的上下文中被不停的重复调用。任何不需要的引用创建都有可能导致内存泄露。1当一个返回一个基础类型的工具函数被调用它必须应该没有局部引用、若全局引用的累积。2当一个返回一个引用类型的工具函数被调用它必须应该没有局部、全局或若全局引用的累积除了要被作为返回值的引用。 一个工具函数以捕获为目的创建一些全局或者弱全局引用这是可接受的因为只有在最开始的时候才会创建这些引用。 如果一个工具函数返回一个引用你应该使返回的引用的类型(例如局部引用、全局引用作为函数规范的一部分。它应该始终如一而不是有时候返回一个局部引用有时候却返回一个全局引用。调用者需要知道工具函数返回的引用的类型以便正确地管理自己的JNI引用。以下代码重复地调用一个工具工具函数GetInfoString。我们需要知道GetInfoString返回的引用的类型以便释放该引用 while (JNI_TRUE) { jstring infoString GetInfoString(info); ... /* process infoString */ ??? /* we need to call DeleteLocalRef, DeleteGlobalRef, or DeleteWeakGlobalRef depending on the type of reference returned by GetInfoString. */ } 在java2 SDK1.2中NewLocalRef函数可以用来保证一个工具函数一直返回一个局部引用。为了说明这个问题我们对MyNewString做一些改动,它缓存了一个被频繁请求的字符串“CommonString”到全局引用 jstring   MyNewString(JNIEnv *env, jchar *chars, jint len) { static jstring result; /* wstrncmp compares two Unicode strings */ if (wstrncmp(CommonString, chars, len) 0) { /* refers to the global ref caching CommonString */ static jstring cachedString NULL; if (cachedString NULL) { /* create cachedString for the first time */ jstring cachedStringLocal ... ; /* cache the result in a global reference */ cachedString (*env)-NewGlobalRef(env, cachedStringLocal); } return (*env)-NewLocalRef(env, cachedString); } ... /* create the string as a local reference and store in result as a local reference */ return result; } 正常的流程返回的时候局部引用。就像之前解释的那样我们必须将缓存字符保存到一个全局引用中这样就可以在多个线程中调用native方法时都能访问它。 return (*env)-NewLocalRef(env, cachedString); 这条语句创建了一个局部引用它指向了缓存在全局引用的指向的统一对象。作为和调用者的约定的一部分MyNewString总是返回一个局部引用。 PushLocalFram、PopLocalFram函数用来管理局部引用的生命周期特别得方便。只需要在native函数的入口调用PushLocalFram在函数退出时调用PopLocalFram局部变量就会被释放。 jobject f(JNIEnv *env, ...) { jobject result; if ((*env)-PushLocalFrame(env, 10) 0) { /* frame not pushed, no PopLocalFrame needed */ return NULL; } ... result ...; if (...) { /* remember to pop local frame before return */ result (*env)-PopLocalFrame(env, result); return result; } ... result (*env)-PopLocalFrame(env, result); /* normal return */ return result; } PopLocalFram函数调用失败时可能会导致未定义的行为例如VM崩溃。 内存泄漏问题Java Heap 的内存泄漏Java 对象存储在 JVM 进程空间中的 Java Heap 中Java Heap 可以在 JVM 运行过程中动态变化。如果 Java 对象越来越多占据 Java Heap 的空间也越来越大JVM 会在运行时扩充 Java Heap 的容量。如果 Java Heap 容量扩充到上限并且在 GC 后仍然没有足够空间分配新的 Java 对象便会抛出 out of memory 异常导致 JVM 进程崩溃。Java Heap 中 out of memory 异常的出现有两种原因——①程序过于庞大致使过多 Java 对象的同时存在②程序编写的错误导致 Java Heap 内存泄漏。多种原因可能导致 Java Heap 内存泄漏。JNI 编程错误也可能导致 Java Heap 的内存泄漏。JVM 中 native memory 的内存泄漏从操作系统角度看JVM 在运行时和其它进程没有本质区别。在系统级别上它们具有同样的调度机制同样的内存分配方式同样的内存格局。JVM 进程空间中Java Heap 以外的内存空间称为 JVM 的 native memory。进程的很多资源都是存储在 JVM 的 native memory 中例如载入的代码映像线程的堆栈线程的管理控制块JVM 的静态数据、全局数据等等。也包括 JNI 程序中 native code 分配到的资源。在 JVM 运行中多数进程资源从 native memory 中动态分配。当越来越多的资源在 native memory 中分配占据越来越多 native memory 空间并且达到 native memory 上限时JVM 会抛出异常使 JVM 进程异常退出。而此时 Java Heap 往往还没有达到上限。多种原因可能导致 JVM 的 native memory 内存泄漏。例如 JVM 在运行中过多的线程被创建并且在同时运行。JVM 为线程分配的资源就可能耗尽 native memory 的容量。JNI 编程错误也可能导致 native memory 的内存泄漏。对这个话题的讨论是本文的重点。 JNI 编程实现了 native code 和 Java 程序的交互因此 JNI 代码编程既遵循 native code 编程语言的编程规则同时也遵守 JNI 编程的文档规范。在内存管理方面native code 编程语言本身的内存管理机制依然要遵循同时也要考虑 JNI 编程的内存管理。本章简单概括 JNI 编程中显而易见的内存泄漏。从 native code 编程语言自身的内存管理和 JNI 规范附加的内存管理两方面进行阐述。Native Code 本身的内存泄漏JNI 编程首先是一门具体的编程语言或者 C 语言或者 C或者汇编或者其它 native 的编程语言。每门编程语言环境都实现了自身的内存管理机制。因此JNI 程序开发者要遵循 native 语言本身的内存管理机制避免造成内存泄漏。以 C 语言为例当用 malloc() 在进程堆中动态分配内存时JNI 程序在使用完后应当调用 free() 将内存释放。总之所有在 native 语言编程中应当注意的内存泄漏规则在 JNI 编程中依然适应。Native 语言本身引入的内存泄漏会造成 native memory 的内存严重情况下会造成 native memory 的 out of memory。Global Reference 引入的内存泄漏JNI 编程还要同时遵循 JNI 的规范标准JVM 附加了 JNI 编程特有的内存管理机制。JNI 中的 Local Reference 只在 native method 执行时存在当 native method 执行完后自动失效。这种自动失效使得对 Local Reference 的使用相对简单native method 执行完后它们所引用的 Java 对象的 reference count 会相应减 1。不会造成 Java Heap 中 Java 对象的内存泄漏。而 Global Reference 对 Java 对象的引用一直有效因此它们引用的 Java 对象会一直存在 Java Heap 中。程序员在使用 Global Reference 时需要仔细维护对 Global Reference 的使用。如果一定要使用 Global Reference务必确保在不用的时候删除。就像在 C 语言中调用 malloc() 动态分配一块内存之后调用 free() 释放一样。否则Global Reference 引用的 Java 对象将永远停留在 Java Heap 中造成 Java Heap 的内存泄漏。 以上是云栖社区小编为您精心准备的的内容在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容欢迎继续使用右上角搜索按钮进行搜索java jni android jni内存泄漏、jni 内存泄漏、jni编程、jni编程指南、jni编程指南中文版以便于您获取更多的相关知识。 转自https://yq.aliyun.com/ziliao/160372
http://www.zqtcl.cn/news/171822/

相关文章:

  • ip网站怎么做酷家乐手机版
  • cnzz统计代码如何添加到网站上去照片网站源码
  • 我的世界电影怎么做的视频网站网页布局实训心得体会
  • 网站建设公司内部情况凡客诚品陈年
  • 浙江建设职业技术学院迎新网站商务网站建设体会
  • 做网站的目的与意义做家教去什么网站
  • 相城网站建设为什么网站建设价格不一
  • 网站icp备案手续我做的网站平台百度搜不到
  • 本溪网站设计公司ps转页面wordpress插件
  • 怎么做短链接网站搜索引擎优化的各种方法
  • 自己做网站怎么挣钱微网站建站系统源码
  • 湖北省网站备案最快几天网站建设存在的具体问题
  • 网站建设算固定资产吗做网站都需要什么软件
  • ui设计培训是什么seo外链网站源码
  • 网站开发浙里建系统平台
  • 建设电影网站的关键国内新闻最新消息2022
  • wordpress 卢晓松玉林做网站优化推广
  • 做户外运动的网站seo内部优化方案
  • 哪个行业必须做网站软件工程最好的出路
  • 安徽省质量提升工程建设网站深圳十大国际外贸公司
  • 县城做信息网站qq是哪个公司
  • 设计师作品展示网站做图软件官方网站
  • 企业网站网站建设价格seo短视频网页入口引流
  • 旅游电商网站建设方案模板济南搜点网络科技有限公司
  • 网站模板 带手机端头条推广平台有哪些
  • 有没有专门做衣服的网站小程序加盟代理前景
  • app网站开发报价wordpress怎么加快网站打开速度
  • 路南网站建设可用的ftp网站
  • 台州市建站公司网站免费建设推荐
  • 网站世界排名怎么做柘城县网站建设