「javajni签名」jdk签名
今天给各位分享javajni签名的知识,其中也会对jdk签名进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、阿里面试官:讲解一下JNI的三种引用
- 2、请教JNI编程中C调用Java实现中NullPointerException问题
- 3、JAVA 里面如何 使用jni 给个例子 加 解释。谢谢
- 4、请问在android开发中,如何问在jni中调用java类的用synchronized修饰的静态方法
- 5、Java 运行时JNI问题
- 6、C调用java时使用JNI的问题!急。。。。。
阿里面试官:讲解一下JNI的三种引用
从Java虚拟机创建的对象传到本地 C/C++ 代码时就会产生引用。根据Java的垃圾回收机制,只要有引用存在就不会触发该引用指向的Java对象的垃圾回收。这些引用在 JNI 中分为三种
全局引用 (Global Reference)
局部引用 (Local Reference)
弱全局引用 (Weak Global Reference), JDK 1.2 引入
最常见的引用类型,基本上通过JNI返回来的引用都是局部引用
例如,使用NewObject就会返回创建出来的实例的局部引用。局部引用只在该native函数中有效,所有在该函数中产生的局部引用,都会在函数返回的时候自动释放(freed)。也可以使用DeleteLocalRef函数进行手动释放该引用。
想一想既然局部引用能够在函数返回时自动释放,为什么还需要DeleteLocalRef函数呢?
实际上局部引用存在,就会防止其指向的对象被垃圾回收。尤其是当一个局部引用指向一个很庞大的对象,或是在一个循环中生成了局部应用;最好的做法就是在使用完该对象后,或在该循环尾部把这个引用释放掉,以确保在垃圾回收器被触发的时候被回收。
在局部引用的有效期中,可以传递到别的本地函数中,要强调的是它的有效期仍然只在一次的Java本地函数调用中,所以千万不能用C++全局变量保存它或是把它定义为C++静态局部变量。
全局引用可以跨越当前线程,在多个native函数中有效,不过需要编程人员手动来释放该引用。全局引用存在期间会防止在Java的垃圾回收的回收。
与局部引用不同,全局引用的创建不是由 JNI 自动创建的,全局引用需要调用 NewGlobalRef 函数,而释放它需要使用 ReleaseGlobalRef 函数。
弱全局应用是 JDK 1.2 新出来的功能,与全局引用相似,创建跟释放都需要由编程人员来进行操作。这种引用与全局引用一样可以在多个本地代码有效,也可以跨越多线程有效;不一样的是,这种引用将不会阻止垃圾回收器回收这个引用所指向的对象。
使用 NewWeakGlobalRef 跟 ReleaseWeakGlobalRef 来产生和释放应用。
IsSameObject 函数对于弱引用全局应用还有一个特别的功能,把NULL传入要比较的对象中,就能够判断弱全局引用所指向的Java对象是否被回收。
获取 jfieldID与jmethodID 的时候会通过该属性/方法名称加上签名来查询相应的 jfieldID/jmethodID。这种查询相对来说开销较大。在开发中可以将这些 FieldID/MethodID 缓存起来,这样就只需要查询一次,以后就使用缓存起来的 FieldID/MethodID。
下面介绍两种缓存方式
在使用时缓存 (Caching at the Point of Use)
在Java类初始化时缓存 (Caching at the Defining Class's Inititalizer)
在native 代码中使用static局部变量来保存已经查询过的jfieldID/jmethodID ,这样就不会在每次的函数调用时查询,而只要一次查询成功后就保存起来了。
不过这种情况下,就不得不考虑多线程同时调用此函数时可能导致同时查询的并发问题,不过这种情况是无害的,因为查询同一个属性或者方法的ID,通常返回的值是一样的。
更好的一个方式就是在任何native函数调用之前把id全部缓存起来。
可以让Java在第一次加载这个类的时候,首先调用本地代码初始化所有的 jfieldID/jmethodID,这样的话就可以省去多次判断id是否存在的冗余代码。当然,这些 jfieldID/jmethodID 是定义在C/C++ 的全局。
使用这种方式还有好处,当Java类卸载或者重新加载的时候,也会重新调用该本地代码来重新计算IDs。
java代码
C/C++ 代码
最简单的Java调用C/C++函数的方法
获取方法/属性的ID;学会了获取/设置属性;还有Java函数的调用
Java/C++之间的字符串的转换问题
在C/C++下如何操作Java的数组
三种引用方式
如何缓存属性/方法的ID
使用了JNI,那么这个Java应用将不能跨平台了。如果要移植到别的平台上,那么native代码就需要重新进行编写
Java是强类型的语言,而C/C++不是。因此,必须在写JNI时倍加小心
总之,必须在构建Java程序的时候,尽量不用或者少用本地代码
附
异常处理
C/C++ 如何启动JVM
JNI与多线程
请教JNI编程中C调用Java实现中NullPointerException问题
java 与 C++ 两种编程语言,它们之间的相互调用:
1、java 调用C++编写的dll,可使用JNI 或 Jawin 开源项目(推荐第二种方法)。
2、C++ 调用java 的变量、方法,通过JNI (Java Native Interface)与java类交互。
----操作步骤(只总结第二个)-----
(1) vc6.0编译C++程序,开发环境设置:工具--》选项--》工具,工具标签下:选择“include files”,加入头文件目录:C:\Program Files\Java\jdk1.5.0\include 和 C:\Program Files\Java\jdk1.5.0\include\win32 ;选择“Libary files"下,加入LIB目录:C:\Program Files\Java\jdk1.5.0\lib 。会编译成exe文件。
执行程序环境设置: Path环境变量加入:C:\Program Files\Java\jdk1.5.0\jre\bin\client (jvm.dll所在目录),若不加入path会提示,执行时找不到jvm.dll.
(2)GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
//([Ljava/lang/String;)V 是main()签名
在java程序目录下执行:javap -s -p ClassDemo (注:ClassDemo.java 已经编译)
取main 下面的语句 :: Signature: ([Ljava/lang/String;)V
(3)附代码示例:
java程序
import java.io.*;
public class DemoMain{
public static void main(String[] args) throws java.io.IOException, java.lang.NullPointerException
{
System.out.println("This is a test.");
}
}
C++程序:
#ifndef __cplusplus
#define __cplusplus
#endif
#include "jni.h"
#include stdio.h
#include stdlib.h
#include windows.h
#pragma comment (lib,"C:\\Program Files\\Java\\jdk1.5.0\\lib\\jvm.lib") // 动态调用lib
#pragma warning(disable: 4129) // 关闭 warning, 4129
void main() {
LoadLibrary("C:\\Program Files\\Java\jre1.5.0\\bin\\client\\jvm.dll"); // 动态调用dll
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
jint res = JNI_CreateJavaVM(jvm, (void**)env, vm_args); // 创建虚拟机
if (res 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};
jclass cls = env-FindClass("DemoMain");
if (cls == 0) printf("Sorry, I can't find the class");
fprintf(stdout, "This is invokeSimplified4.\n");
jmethodID get_main_id;
if(cls != NULL)
{
get_main_id =env-GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
fprintf(stdout, "This is invokeSimplified5.\n");
if(get_main_id != NULL )
{
jclass string = env-FindClass("java/lang/String");
jobjectArray args = env-NewObjectArray(0,string, NULL);
fprintf(stdout, "This is invokeSimplified6.\n");
int i = env-CallIntMethod(cls, get_main_id, args);
fprintf(stdout, i+ "This is invokeSimplified7.\n");
}
}
jvm-DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}
JAVA 里面如何 使用jni 给个例子 加 解释。谢谢
JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。
JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。
简单介绍及应用如下:
一、JAVA中所需要做的工作
在JAVA程序中,首先需要在类中声明所调用的库名称,如下:
static {
System.loadLibrary(“goodluck”);
}
在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。
还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具 体实现。如下:
public native static void set(int i);
public native static int get();
然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。
例如程序testdll.java,内容为:
public class testdll
{
static
{
System.loadLibrary("goodluck");
}
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}
用javac testdll.java编译它,会生成testdll.class。
再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。
二、C/C++中所需要做的工作
对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。
接上例子。我们先看一下testdll.h文件的内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include jni.h
/* Header for class testdll */
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: testdll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
/*
* Class: testdll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
在具体实现的时候,我们只关心两个函数原型
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。
好,下面我们用testdll.cpp文件具体实现这两个函数:
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll 。把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。
请问在android开发中,如何问在jni中调用java类的用synchronized修饰的静态方法
那个返回类型可能也需要加上分号结尾。看图中有文本编辑器打开一个 class 文件的例子。synchronized 本身不是签名的一部分,按理说它仅影响执行时的过程,不影响查找方法本身。
Java 运行时JNI问题
1、在执行java的时候,要输入完整的包名+类名。否则在以后的测试调用过程中会发生java.lang.UnsatisfiedLinkError这个异常。
2、错误的详细信息。
3、CLASSPATH、PATH。
4、写入程序出现问题
Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。
C调用java时使用JNI的问题!急。。。。。
M,是其中的一个组成部分,更详细的看下面:
----------------------------------
操作系统装入jvm是通过jdk中java.exe来完成,通过下面4步来完成jvm环境.
1.创建jvm装载环境和配置
2.装载jvm.dll
3.初始化jvm.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类。
在我们运行和调试java程序的时候,经常会提到一个jvm的概念.jvm是java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间.
首先来说一下jdk这个东西,不管你是初学者还是高手,是j2ee程序员还是j2se程序员,jdk总是在帮我们做一些事情.我们在了解java之前首先大师们会给我们提供说jdk这个东西.它在java整个体系中充当着什么角色呢?我很惊叹sun大师们设计天才,能把一个如此完整的体系结构化的如此完美.jdk在这个体系中充当一个生产加工中心,产生所有的数据输出,是所有指令和战略的执行中心.本身它提供了java的完整方案,可以开发目前java能支持的所有应用和系统程序.这里说一个问题,大家会问,那为什么还有j2me,j2ee这些东西,这两个东西目的很简单,分别用来简化各自领域内的开发和构建过程.jdk除了jvm之外,还有一些核心的API,集成API,用户工具,开发技术,开发工具和API等组成
好了,废话说了那么多,来点于主题相关的东西吧.jvm在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的java运行环境,因此也就虚拟计算机. 操作系统装入jvm是通过jdk中java.exe来完成,通过下面4步来完成jvm环境.
1.创建jvm装载环境和配置
2.装载jvm.dll
3.初始化jvm.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类。
一.jvm装入环境,jvm提供的方式是操作系统的动态连接文件.既然是文件那就一个装入路径的问题,java是怎么找这个路径的呢?当你在调用java test的时候,操作系统会在path下在你的java.exe程序,java.exe就通过下面一个过程来确定jvm的路径和相关的参数配置了.下面基于windows的实现的分析.
首先查找jre路径,java是通过GetApplicationHome api来获得当前的java.exe绝对路径,c:\j2sdk1.4.2_09\bin\java.exe,那么它会截取到绝对路径c:\j2sdk1.4.2_09\,判断c:\j2sdk1.4.2_09\bin\java.dll文件是否存在,如果存在就把c:\j2sdk1.4.2_09\作为jre路径,如果不存在则判断c:\j2sdk1.4.2_09\jre\bin\java.dll是否存在,如果存在这c:\j2sdk1.4.2_09\jre作为jre路径.如果不存在调用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号”\JavaHome的路径为jre路径。
然后装载jvm.cfg文件JRE路径+\lib+\ARCH(CPU构架)+\jvm.cfgARCH(CPU构架)的判断是通过java_md.c中GetArch函数判断的,该函数中windows平台只有两种情况:WIN64的‘ia64’,其他情况都为‘i386’。以我的为例:C:\j2sdk1.4.2_09\jre\lib\i386\jvm.cfg.主要的内容如下:
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
在我们的jdk目录中jre\bin\server和jre\bin\client都有jvm.dll文件存在,而java正是通过jvm.cfg配置文件来管理这些不同版本的jvm.dll的.通过文件我们可以定义目前jdk中支持那些jvm,前面部分(client)是jvm名称,后面是参数,KNOWN表示jvm存在,ALIASED_TO表示给别的jvm取一个别名,WARN表示不存在时找一个jvm替代,ERROR表示不存在抛出异常.在运行java XXX是,java.exe会通过CheckJvmType来检查当前的jvm类型,java可以通过两种参数的方式来指定具体的jvm类型,一种按照jvm.cfg文件中的jvm名称指定,第二种方法是直接指定,它们执行的方法分别是“java -J”、“java -XXaltjvm=”或“java -J-XXaltjvm=”。如果是第一种参数传递方式,CheckJvmType函数会取参数‘-J’后面的jvm名称,然后从已知的jvm配置参数中查找如果找到同名的则去掉该jvm名称前的‘-’直接返回该值;而第二种方法,会直接返回“-XXaltjvm=”或“-J-XXaltjvm=”后面的jvm类型名称;如果在运行java时未指定上面两种方法中的任一一种参数,CheckJvmType会取配置文件中第一个配置中的jvm名称,去掉名称前面的‘-’返回该值。CheckJvmType函数的这个返回值会在下面的函数中汇同jre路径组合成jvm.dll的绝对路径。如果没有指定这会使用jvm.cfg中第一个定义的jvm.可以通过set _JAVA_LAUNCHER_DEBUG=1在控制台上测试.
最后获得jvm.dll的路径,JRE路径+\bin+\jvm类型字符串+\jvm.dll就是jvm的文件路径了,但是如果在调用java程序时用-XXaltjvm=参数指定的路径path,就直接用path+\jvm.dll文件做为jvm.dll的文件路径.
二:装载jvm.dll
通过第一步已经找到了jvm的路径,java通过LoadJavaVM来装入jvm.dll文件.装入工作很简单就是调用windows API函数:
LoadLibrary装载jvm.dll动态连接库.然后把jvm.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。jvm.dll的装载工作宣告完成。
三:初始化jvm,获得本地调用接口,这样就可以在java中调用jvm的函数了.调用InvocationFunctions-CreateJavaVM也就是jvm中JNI_CreateJavaVM方法获得JNIEnv结构的实例.
四:运行java程序.
java程序有两种方式一种是jar包,一种是class. 运行jar,java -jar XXX.jar运行的时候,java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用java类java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main函数直接调用java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用java.c中LoadClass方法装载该类。
然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中
“public static void main(String[] args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的
CallStaticVoidMethod方法调用该java类的main方法。
另外,虚机团上产品团购,超级便宜
javajni签名的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于jdk签名、javajni签名的信息别忘了在本站进行查找喔。
发布于:2022-12-09,除非注明,否则均为
原创文章,转载请注明出处。