精华内容
下载资源
问答
  • 局部和全局变量浅析

    千次阅读 2017-10-12 00:31:32
    变量有分全局变量和局部变量 也分静态变量普通变量 先说全局变量和局部变量的区别: 1.存储位置不同:全局变量存储在方法区,局部变量存储在栈区 2.生命周期不同:全局变量的生命期和主程序一样,随着程序的...

    变量有分全局变量和局部变量 也分静态变量和普通变量

    先说全局变量和局部变量的区别:

    1.存储位置不同:全局变量存储在方法区,局部变量存储在栈区

    2.生命周期不同:全局变量的生命期和主程序一样,随着程序的销毁而销毁,局部变量在函数内部,函数退出了就不存在

    3.使用方式不同:全局变量在声明后程序的各个部分都可以用到,但是局部变量只能在局部使用。函数内部会优先使用局部变量再使用全局变量

    注意:局部变量不能赋值为同名全局的值

    int value =1

    int main(){

       int value = value;

       syste.out.printf(value+"");


    }


    程序输出-34323322 因为局部变量会覆盖全局变量,局部变量没有赋值 因此输出随便值


    java中成员变量(全局变量) 成员变量好比试正式员工,而局部变量就是临时工,随时销毁,成员变量伴随着对象。


    静态变量和普通变量的区别

    最明显的特性:全局静态变量属于类,成员变量属于对象

    类的静态变量在内存只有一个,java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享,静态变量通过类名.xxx进行访问,生命周期取决于类的生命周期。

    成员变量取决于类的实例,每创建一个实例,java虚拟机就会为实例变量分配一次内存,实例变量位于堆。

    java中初始化顺序:加载类,静态变量初始化,静态快,成员变量 构造方法

    static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
    static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
    static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝


    成员变量存储在堆内存的对象中,所以也叫对象的特有数据。            

    静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。



    展开全文
  • 031 局部和全局变量

    千次阅读 2015-12-27 20:36:12
    C 语言 全局变量和局部变量的区别

    C 语言 全局变量和局部变量的区别


    /********************031 局部和全局变量************************
     * 局部变量和全局变量   
     * C语言精彩编程百例 第31 */
     
     #include <stdio.h>
     
     int quanju; //全局变量 count
     
     void func1(); //函数声明
     void func2();
     
     void main()
     {
    	 quanju = 100; 
    	 func1();
     }
     
     void func1() 
     {
    	 int temp;
    	 temp = quanju;
    	 func2();
    	 printf("quanju is %d\n",quanju);
    	 func2();
     }
     
     void func2()
     {
    	 int quanju;
    	 for (quanju=1;quanju<20;quanju++)
    		 printf(".");
    	 printf("\n");
     }
     
    

    担心 count是伪代码或保留字之类的东西, 吧count改为quanju 以便观察, 实际证明

    没这回事儿

    使用mingw gcc编译器 gcc  031.c -S -o 031.s 得出汇编代码


    	.file	"031.c"
    	.comm	_quanju, 4, 2  #全局变量
    	.def	___main;	.scl	2;	.type	32;	.endef
    	.text
    	.globl	_main
    	.def	_main;	.scl	2;	.type	32;	.endef
    _main:
    LFB10:
    	.cfi_startproc
    	pushl	%ebp
    	.cfi_def_cfa_offset 8
    	.cfi_offset 5, -8
    	movl	%esp, %ebp
    	.cfi_def_cfa_register 5
    	andl	$-16, %esp     
    	call	___main        
    	movl	$100, _quanju  # _quanju = 100
    	call	_func1
    	leave
    	.cfi_restore 5
    	.cfi_def_cfa 4, 4
    	ret
    	.cfi_endproc
    LFE10:
    	.section .rdata,"dr"
    LC0:
    	.ascii "quanju is %d\12\0"
    	.text
    	.globl	_func1
    	.def	_func1;	.scl	2;	.type	32;	.endef
    _func1:
    LFB11:
    	.cfi_startproc
    	pushl	%ebp
    	.cfi_def_cfa_offset 8
    	.cfi_offset 5, -8
    	movl	%esp, %ebp
    	.cfi_def_cfa_register 5
    	subl	$40, %esp
    	movl	_quanju, %eax
    	movl	%eax, -12(%ebp)	#temp = _quanju
    	call	_func2
    	movl	_quanju, %eax
    	movl	%eax, 4(%esp)   # printf 函数参数传入
    	movl	$LC0, (%esp)    # printf 字符串传入
    	call	_printf
    	call	_func2
    	leave
    	.cfi_restore 5
    	.cfi_def_cfa 4, 4
    	ret
    	.cfi_endproc
    LFE11:
    	.globl	_func2
    	.def	_func2;	.scl	2;	.type	32;	.endef
    _func2:
    LFB12:
    	.cfi_startproc
    	pushl	%ebp
    	.cfi_def_cfa_offset 8
    	.cfi_offset 5, -8
    	movl	%esp, %ebp
    	.cfi_def_cfa_register 5
    	subl	$40, %esp
    	movl	$1, -12(%ebp)     # 局部变量 quanju = 1  
    	jmp	L4
    L5:
    	movl	$46, (%esp)        # _putchar参数传入 $46 就是 "."
    	call	_putchar
    	addl	$1, -12(%ebp)      # 局部变量 quanju + = 1
    L4:
    	cmpl	$19, -12(%ebp)     # 比较 quanju 和 19
    	jle	L5                     # 小于等于跳
    	movl	$10, (%esp)        # 换行
    	call	_putchar
    	leave
    	.cfi_restore 5
    	.cfi_def_cfa 4, 4
    	ret
    	.cfi_endproc
    LFE12:
    	.ident	"GCC: (GNU) 4.8.1"
    	.def	_printf;	.scl	2;	.type	32;	.endef
    	.def	_putchar;	.scl	2;	.type	32;	.endef
    

    局部变量都是在函数的栈中分配内存并通过 %ebp偏移寻址 。 

    由此可见两种方式的主要区别: 

     1. 内存分配的方式。 全局变量在程序的内存空间中直接分配, 局部变量在函数的栈空间分配空间。 

     2. 寻址方式, 全局变量通过符号链接直接寻址, 局部变量通过%ebp偏移寻址。


    编译的汇编代码中出现一些cfi伪指令, 这个东西生产的东西没有出现在代码中,代码反编译的内容和汇编代码还是一致的。

    不过反编译内容开头给出的一大堆完全不明白的东西, 从objdump的描述来看是两个部分: exception handler 和 CRTStarup 。

    目前这个部分还没开始研究。


    
    展开全文
  • 一个变量不可能既是局部变量,又是全局变量。 全局作用域的变量,在程序被销毁时候,全局变量就会被丢弃。 局部作用域的变量,在局部运行完后,局部变量也就会被丢弃。 全局作用域的代码不能使用任何局部变量。 ...

    欢迎关注小睿的微信公众号:郭小睿同学,每天更新小知识、笔记、案例、学习资源~
    在这里插入图片描述
    在这里插入图片描述
    在被调用函数赋值的变元和变量,处于该函数的局部作用域
    在所有函数之外赋值的变量,属于全局作用域

    处于局部作用域的变量,叫局部变量
    处于全局作用域的变量,叫全局变量

    一个变量不可能既是局部变量,又是全局变量
    在这里插入图片描述

    全局作用域的变量,在程序被销毁时候,全局变量就会被丢弃。
    局部作用域的变量,在局部运行完后,局部变量也就会被丢弃。

    • 全局作用域的代码不能使用任何局部变量。
    • 但是局部作用域可以访问全局变量。
    • 一个函数的局部作用域的中的代码,不能使用其他局部作用域中的变量。
    • 可以在不同的作用域中,用相同的名字命名不同的变量。

    如果所有变量都定义为全局变量,当使用特定函数修改变量时,别的地方再次使用其变量值的时候,就会受到影响。
    因此在小程序中使用全局变量不会造成太大的问题,但是在大程序中,依赖全局变量就是一个坏的习惯。

    一般在实际开发中,我们应该避免在不同的作用域使用相同变量名,防止追踪某一时刻使用的是哪个变量,引起不必要的麻烦。
    在这里插入图片描述

    global语句

    如果需要一个函数修改全局变量,应该使用global语句

    def spam():
       global eggs
       eggs = "spam"
    
    
    eggs = "global"
    spam()
    print(eggs)
    

    控制台输出:
    输出
    在这里插入图片描述

    程序剖析

    eggs是全局变量,但是在spam()函数中,我们针对eggs变量使用了global关键字,因此在局部修改了eggs变量的值。
    在这里插入图片描述

    展开全文
  • JNI学习笔记——局部和全局引用

    万次阅读 2012-03-26 22:51:04
    JNI将实例、数组类型暴露为不透明的引用。native代码从不会直接检查一个不透明的引用指针的上下文,而是通过使用JNI函数来访问由不透明的引用所指向的数据结构。因为只处理不透明的引用,这样就不需要...2)局部和全局

    JNI将实例、数组类型暴露为不透明的引用。native代码从不会直接检查一个不透明的引用指针的上下文,而是通过使用JNI函数来访问由不透明的引用所指向的数据结构。因为只处理不透明的引用,这样就不需要担心不同的java VM实现而导致的不同的内部对象的布局。然而,还是有必要了解一下JNI中不同种类的引用:

    1)JNI 支持3中不透明的引用:局部引用、全局引用和弱全局引用。

    2)局部和全局引用,有着各自不同的生命周期。局部引用能够被自动释放,而全局引用和若全局引用在被程序员释放之前,是一直有效的。

    3)一个局部或者全局引用,使所提及的对象不能被垃圾回收。而弱全局引用,则允许提及的对象进行垃圾回收。

    4)不是所有的引用都可以在所有上下文中使用的。例如:在一个创建返回引用native方法之后,使用一个局部引用,这是非法的。



    局部和全局引用


    那么到底什么是局部引用,什么事全局引用,它们有什么不同?



    局部引用


    多数JNI函数都创建局部引用。例如JNI函数NewObject创建一个实例,并且返回一个指向该实例的局部引用。

    局部引用只在创建它的native方法的动态上下文中有效,并且只在native方法的一次调用中有效。所有局部引用只在一个native方法的执行期间有效,在该方法返回时,它就被回收。

    在native方法中使用一个静态变量来保存一个局部引用,以便在随后的调用中使用该局部引用,这种方式是行不通的。例如以下例子,误用了局部引用:
    1. /* This code is illegal */  
    2. jstring  
    3. MyNewString(JNIEnv *env, jchar *chars, jint len)  
    4. {  
    5.     static jclass stringClass = NULL;  
    6.     jmethodID cid;  
    7.     jcharArray elemArr;  
    8.     jstring result;  
    9.     if (stringClass == NULL) {  
    10.         stringClass = (*env)->FindClass(env, "java/lang/String");  
    11.         if (stringClass == NULL) {  
    12.             return NULL; /* exception thrown */  
    13.         }  
    14.     }  
    15.     /* It is wrong to use the cached stringClass here, 
    16.        because it may be invalid. */  
    17.     cid = (*env)->GetMethodID(env, stringClass, "<init>""([C)V");  
    18.     ...  
    19.     elemArr = (*env)->NewCharArray(env, len);  
    20.     ...  
    21.     result = (*env)->NewObject(env, stringClass, cid, elemArr);  
    22.     (*env)->DeleteLocalRef(env, elemArr);  
    23.     return result;  
    24. }  
    这种保存局部引用的方式是不正确的,因为FindClass()返回的是对java.lang.String的局部引用。这是因为,在native代码从MyNewString返回退出时,VM 会释放所有局部引用,包括存储在stringClass变量中的指向类对象的引用。这样当再次后继调用MyNewString时,可能会访问非法地址,导致内存被破坏,或者系统崩溃。

    局部引用失效,有两种方式:‘
    1)系统会自动释放局部变量。
    2)程序员可以显示地管理局部引用的生命周期,例如调用DeleteLocalRef。

    一个局部引用可能在被摧毁之前,被传给多个native方法。例如,MyNewString中,返回一个由NewObject创建的字符串引用,它将由NewObject的调用者来决定是否释放该引用。而在以下代码中:
    1. JNIEXPORT jstring JNICALL Java_C_f(JNIEnv *env, jobject this) {  
    2.       char *c_str = ...<pre name="code" class="cpp">      ... <pre name="code" class="cpp">return MyNewString(c_str);<pre name="code" class="cpp">}  
    
    
    
    
    
    
    在VM接收到来自Java_C_f的局部引用以后,将基础字符串对象传递给ava_C_f的调用者,然后摧毁原本由MyNewString中调用的JNI函数NewObject所创建的局部引用。

    局部对象只属于创建它们的线程,只在该线程中有效。一个线程想要调用另一个线程创建的局部引用是不被允许的。将一个局部引用保存到全局变量中,然后在其它线程中使用它,这是一种错误的编程。



    全局引用


    在一个native方法被多次调用之间,可以使用一个全局引用跨越它们。一个全局引用可以跨越多个线程,并且在被程序员释放之前,一致有效。和局部引用一样,全局引用保证了所引用的对象不会被垃圾回收。

    和局部引用不一样(局部变量可以由多数JNI函数创建),全局引用只能由一个JNI函数创建(NewGlobalRef)。下面是一个使用全局引用版本的MyNewString:
    1. /* This code is OK */  
    2. jstring  
    3. MyNewString(JNIEnv *env, jchar *chars, jint len)  
    4. {  
    5.     static jclass stringClass = NULL;  
    6.     ...  
    7.     if (stringClass == NULL) {  
    8.         jclass localRefCls =  
    9.             (*env)->FindClass(env, "java/lang/String");  
    10.         if (localRefCls == NULL) {  
    11.             return NULL; /* exception thrown */  
    12.         }  
    13.         /* Create a global reference */  
    14.         stringClass = (*env)->NewGlobalRef(env, localRefCls);  
    15.         /* The local reference is no longer useful */  
    16.         (*env)->DeleteLocalRef(env, localRefCls);  
    17.         /* Is the global reference created successfully? */  
    18.         if (stringClass == NULL) {  
    19.             return NULL; /* out of memory exception thrown */  
    20.         }  
    21.     }  
    22.     ...  
    23. }  



    弱全局引用


    弱全局引用是在java 2 SDK1.2才出现的。它由NewGolableWeakRef函数创建,并且被DeleteGloablWeakRef函数摧毁。和全局引用一样,它可以跨native方法调用,也可以跨越不同线程。但是和全局引用不同的是,它不阻止对基础对象的垃圾回收。下面是弱全局引用版的MyNewString:
    1. JNIEXPORT void JNICALL  
    2. Java_mypkg_MyCls_f(JNIEnv *env, jobject self)  
    3. {  
    4.     static jclass myCls2 = NULL;  
    5.     if (myCls2 == NULL) {  
    6.         jclass myCls2Local =  
    7.             (*env)->FindClass(env, "mypkg/MyCls2");  
    8.         if (myCls2Local == NULL) {  
    9.             return/* can’t find class */  
    10.         }  
    11.         myCls2 = NewWeakGlobalRef(env, myCls2Local);  
    12.         if (myCls2 == NULL) {  
    13.             return/* out of memory */  
    14.         }  
    15.     }  
    16.     ... /* use myCls2 */  
    17. }  
    弱全局引用在一个被native代码缓存着的引用不想阻止基础对象被垃圾回收时,非常有用。如以上例子,mypkg.MyCls.f需要缓存mypkg.MyCls2的引用。而通过将mypkg.MyCls2缓存到弱引用中,能够实现MyCls2类依旧可以被卸载。

    上面代码中,我们假设了MyCls类和MyCls2类的生命周期是相同的(例如,在同一个类中被加载、卸载)。所以没有考虑MyCls2被卸载了,然后在类MyCls和native方法的实现Java_mypkg_MyCls_f还要被继续使用时,再被重新加载起来的情况。针对于这个MyCls2类可能被卸载再加载的情况,在使用时,需要检查该弱全局引用是否还有效。如何检查,这将在下面提到。



    比较引用


    可以用JNI函数IsSameObject来检查给定的两个局部引用、全局引用或者弱全局引用,是否指向同一个对象。
    1. (*env)->IsSameObject(env, obj1, obj2)  
    返回值为:
    JNI_TRUE,表示两个对象一致,是同一个对象。
    JNI_FALSE,表示两个对象不一致,不是同一个对象。

    在java VM中NULL是null的引用。
    如果一个对象obj是局部引用或者全局引用,则可以这样来检查它是否指向null对象:
    1. (*env)->IsSameObject(env, obj, NULL)  
    或者:
    1. NULL == obj  

    而对于弱全局引用,以上规则需要改变一下:
    我们可以用这个函数来判断一个非0弱全局引用wobj所指向的对象是否仍旧存活着(依旧有效)。
    1. (*env)->IsSameObject(env, wobj, NULL)  
    返回值:
    JNI_TRUE,表示对象已经被回收了。
    JNI_FALSE,表示wobj指向的对象,依旧有效。


    释放引用

    除了引用的对象要占用内存,每个JNI引用本身也会消耗一定内存。作为一个JNI程序员,应该对在一段给定的时间里,程序会用到的引用的个数,做到心中有数。特别是,尽管程序所创建的局部引用最终会被VM会被自动地释放,仍旧需要知道在程序在执行期间的任何时刻,创建的局部引用的上限个数。创建过多的引用,即便他们是瞬间、短暂的,也会导致内存耗尽。

    释放局部引用

    多数情况下,在执行一个native方法时,你不需要担心局部引用的释放,java VM会在native方法返回调用者的时候释放。然而有时候需要JNI程序员显示的释放局部引用,来避免过高的内存使用。那么什么时候需要显示的释放呢,且看一下情景:
    1)在单个native方法调用中,创建了大量的局部引用。这可能会导致JNI局部引用表溢出。此时有必要及时地删除那些不再被使用的局部引用。例如以下代码,在该循环中,每次都有可能创建一个巨大的字符串数组。在每个迭代之后,native代码需要显示地释放指向字符串元素的局部引用:

    1. for (i = 0; i < len; i++) {  
    2.     jstring jstr = (*env)->GetObjectArrayElement(env, arr, i);  
    3.     ... /* process jstr */  
    4.     (*env)->DeleteLocalRef(env, jstr);  
    5. }  

    2)你可能要创建一个工具函数,它会被未知的上下文调用。例如之前提到到MyNewString这个例子,它在每次返回调用者欠,都及时地将局部引用释放。

    3)native方法,可能不会返回(例如,一个可能进入无限事件分发的循环中的方法)。此时在循环中释放局部引用,是至关重要的,这样才能不会无限期地累积,进而导致内存泄露。

    4)native方法可能访问一个巨大的对象,因此,创建了一个指向该对象的局部引用。native方法在返回调用者之前,除访问对象之外,还执行了额外的计算。指向这个大对象的局部引用,将会包含该对象,以防被垃圾回收。这个现象会持续到native方法返回到调用者时,即便这个对象不会再被使用,也依旧会受保护。在以下例子中,由于在lengthyComputation()前,显示地调用了DeleteLocalRef,所以垃圾回收器有机会可以释放lref所指向的对象。
    1. /* A native method implementation */  
    2. JNIEXPORT void JNICALL  
    3. Java_pkg_Cls_func(JNIEnv *env, jobject this)  
    4. {  
    5.     lref = ...              /* a large Java object */  
    6.     ...                     /* last use of lref */  
    7.     (*env)->DeleteLocalRef(env, lref);  
    8.     lengthyComputation();   /* may take some time */  
    9.     return;                 /* all local refs are freed */  
    10. }  
    这个情形的实质,就是允许程序在native方法执行期间,java的垃圾回收机制有机会回收native代码不在访问的对象。

    在java 2 SDK1.2中管理局部引用


    不知道java 7怎么样了,应该更强大吧,有时间,去看看,这里且按照java2的特性来吧。

    SDK1.2中提供了一组额外的函数来管理局部引用的生命周期。他们是EnsureLocalCapacity、NewLocalRef、PushLocalFram以及PopLocalFram。

    JNI的规范要求VM可以自动确保每个native方法可以创建至少16个局部引用。经验显示,如果native方法中未包含和java VM的对象进行复杂的互相操作,这个容量对大多数native方法而言,已经足够了。如果,出现这还不够的情况,需要创建更多的局部引用,那么native方法可以调用EnsureLocalCapacity来保证这些局部引用有足够的空间。
    1. /* The number of local references to be created is equal to 
    2.    the length of the array. */  
    3. if ((*env)->EnsureLocalCapacity(env, len)) < 0) {  
    4.     ... /* out of memory */  
    5. }  
    6. for (i = 0; i < len; i++) {  
    7.     jstring jstr = (*env)->GetObjectArrayElement(env, arr, i);  
    8.     ... /* process jstr */  
    9.     /* DeleteLocalRef is no longer necessary */  
    10. }  
    这样做,所消耗的内存,自然就有可能比之前的版本来的多。

    另外,PushLocalFram\PopLocalFram函数允许程序员创建嵌套作用域的局部引用。如下代码:
    1. #define N_REFS ... /* the maximum number of local references  
    2.   used in each iteration */  
    3. for (i = 0; i < len; i++) {  
    4.     if ((*env)->PushLocalFrame(env, N_REFS) < 0) {  
    5.         ... /* out of memory */  
    6.     }  
    7.     jstr = (*env)->GetObjectArrayElement(env, arr, i);  
    8.     ... /* process jstr */  
    9.     (*env)->PopLocalFrame(env, NULL);  
    10. }  
    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返回的引用的类型,以便释放该引用:
    1. while (JNI_TRUE) {  
    2.     jstring infoString = GetInfoString(info);  
    3.     ... /* process infoString */  
    4.     ??? /* we need to call DeleteLocalRef, DeleteGlobalRef, 
    5.   or DeleteWeakGlobalRef depending on the type of 
    6.   reference returned by GetInfoString. */  
    7. }  

    在java2 SDK1.2中,NewLocalRef函数可以用来保证一个工具函数一直返回一个局部引用。为了说明这个问题,我们对MyNewString做一些改动,它缓存了一个被频繁请求的字符串(“CommonString”)到全局引用:
    1. jstring  
    2. MyNewString(JNIEnv *env, jchar *chars, jint len)  
    3. {  
    4.     static jstring result;  
    5.     /* wstrncmp compares two Unicode strings */  
    6.     if (wstrncmp("CommonString", chars, len) == 0) {  
    7.         /* refers to the global ref caching "CommonString" */  
    8.         static jstring cachedString = NULL;  
    9.         if (cachedString == NULL) {  
    10.             /* create cachedString for the first time */  
    11.             jstring cachedStringLocal = ... ;  
    12.             /* cache the result in a global reference */  
    13.             cachedString =  
    14.                 (*env)->NewGlobalRef(env, cachedStringLocal);  
    15.         }  
    16.         return (*env)->NewLocalRef(env, cachedString);  
    17.     }  
    18.     ... /* create the string as a local reference and store in 
    19.   result as a local reference */  
    20.     return result;  
    21. }  
    正常的流程返回的时候局部引用。就像之前解释的那样,我们必须将缓存字符保存到一个全局引用中,这样就可以在多个线程中调用native方法时,都能访问它。
    1. return (*env)->NewLocalRef(env, cachedString);  
    这条语句,创建了一个局部引用,它指向了缓存在全局引用的指向的统一对象。作为和调用者的约定的一部分,MyNewString总是返回一个局部引用。

    PushLocalFram、PopLocalFram函数用来管理局部引用的生命周期特别得方便。只需要在native函数的入口调用PushLocalFram,在函数退出时调用PopLocalFram,局部变量就会被释放。
    1. jobject f(JNIEnv *env, ...)  
    2. {  
    3.     jobject result;  
    4.     if ((*env)->PushLocalFrame(env, 10) < 0) {  
    5.         /* frame not pushed, no PopLocalFrame needed */  
    6.         return NULL;  
    7.     }  
    8.     ...  
    9.     result = ...;  
    10.     if (...) {  
    11.         /* remember to pop local frame before return */  
    12.         result = (*env)->PopLocalFrame(env, result);  
    13.         return result;  
    14.     }  
    15.     ...  
    16.     result = (*env)->PopLocalFrame(env, result);  
    17.     /* normal return */  
    18.     return result;  
    19. }  
    PopLocalFram函数调用失败时,可能会导致未定义的行为,例如VM崩溃。
    展开全文
  • 大多数JNI函数返回局部引用,局部引用不能在后续的调用中被缓存及重用 一旦原生函数返回,局部引用立即被释放 例如FindClass函数返回一个局部引用,当原生方法返回时,它被自动释放,也可以用DeleteLocalRef函数显式释放...
  • JNI将实例、数组类型暴露为不透明的引用。native代码从不会直接检查一个不透明的引用指针的上下文,而是通过使用JNI函数来访问由不透明的引用所指向的数据结构。因为只处理不透明的引用,这样...2)局部和全局引用,有
  • 示例1:修改全局变量值在函数中使用global关键字表示使用(修改)的是全局变量。num = 100 def func(): global num num = 200 x = num + 100 print(x) #print 300func() print num # print 200示例2:局部同名...
  • 设置全局过滤配置文件 .gitignore_global 后,如果在某个版本库里也设置了.gitignore (局部过滤配置文件),那 **git 会优先考虑局部的过滤规则,然后再考虑全局**
  • Vue过滤器(局部和全局过滤)

    千次阅读 2019-06-26 19:28:49
    过滤器 什么是过滤器? 用来格式化数据的一个函数 例如: $ 10 ‘$’ + price 日期的格式化 Vue 1.x 版本借鉴了 angular , 提供 10 个过滤器, 包括有: 日期 小数点位数保留 货币 ...全局定义过滤器 <p> ...
  • C++中局部和全局变量的地址分配

    千次阅读 2016-11-22 11:12:42
    变量的分类以及初始化情况:局部变量,全局变量,静态的,非静态的。C++里面又包括成员变量。 一. 局部变量 编译器按照内存地址递减的方式来给变量分配内存 局部变量很多书籍中也叫自动变量,它声明在函数...
  • 这JNI支持三张类型的引用:局部引用,全局引用弱引用。  局部引用  局部引用不能被缓存重复使用在一系列的调用因为他们的生命周期被限制在本地的方法。本地引用被释放一旦本地的方法返回。例如,这个...
  • 1.先下载安装node-sass一些加载器 $ cnpm install sass-loader node-sass vue-style-loader --D 2.配置webpake加载器:webpack.base.config.js //从这一段上面是默认的!不用改!下面是没有的需要你手动添加,...
  • extensions: "base" // 返回地址描述以及附近兴趣点道路信息,默认"base" }); }); console.info('MGeocoder1:'+MGeocoder); return MGeocoder; } ``` 就是上面这段代码,在谷歌浏览器可以输出...
  • 学会区分局部变量和全局变量,明白静态变量的作用。 另外,了解一下,extern这个声明变量的关键字。 今天学了局部变量,全局变量,还有外部和内部链接,了解作用域,其中,一段有趣的代码,计算count最终的值和sum的...
  • 不用任何局部和全局变量实现int strlen(char *a)int strlen(char *a) { if(0 == *a) return 0; else return 1 + strlen(a + 1);
  • 局部引用 大多数JNI函数返回局部引用。局部引用不能在后续的调用中被缓存及重用,主要是因为它们的使用期限仅限于原生方法,一旦原生函数返回,局部引用即被释放。例如,使用FindClass函数返回一个局部引用,当原生...
  • 自定义类型转换器--局部和全局

    千次阅读 2012-10-06 12:30:16
    在Struts2框架中使用自定义类型转换器需要...注册局部类型转换器需要建立一个命名规则为ActionName-conversion.properties的属性文件,该属性文件保存在与Action类文件相同的目录下。ActionName就是使用类型转换器的Ac
  • 针对tikzpicture和caption之间的空白距离,可采用局部方法和全局方法来调整,具体如下: 局部方法,即对单个图进行处理: 在tikzpicture和caption之间添加\vspace*{3mm}即可 \begin{figure} \begin{tikzpicture} ...
  • 并行编码是分别编码局部和全局知识,然后再把二者拼接起来;级联编码是先进行全局编码,然后将得到的全局编码特征向量作为局部编码的输入,再得到最后的结果。 同时,这两种方法都有层级和非层级之分。非层级即各自...
  • 但是产品开发者重在应用程序的开发产品的研发,编译器是一个工具,要是在这个上面花很多时间的话,市场有可能已经被别人抢占了。所以我不建议他们去深入编译环境,只要能用就行。所以我在这里给大家推荐一种方法:...
  • java的局部变量和全局变量

    千次阅读 2019-03-19 09:22:37
    关于Java代码变量问题——局部和全局 在说明问题之前,先看一道蓝桥杯的题目: 立方变自身 观察下面的现象,某个数字的立方,按位累加仍然等于自身。 1^3 = 1 8^3 = 512 5+1+2=8 17^3 = 4913 4+9+1+3=17 … 请你计算...
  • 局部变量和全局变量

    2016-03-16 21:59:18
    局部变量和全局变量 1.在子程序中定义的变量称为局部变量,在程序一开始定义的变量称为全局变量。 2.全局变量作用域为整个程序,局部变量作用域是定义该变量的子程序。 3.当局部变量与全局变量同名时,在C语言中,...
  • 变量的作用域  定义变量有三种情况:  1.在函数的开头定义 包含函数的实参列表 (只在本函数内有效)  2.在函数内的符合语句中定义 (只在符合...  3.... 12是局部变量,3是外部变量(全局变量)  (c的一个习

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,659
精华内容 12,663
关键字:

局部和全局