java 中本地方法调用---native关键字
2013-02-08 17:43
148 查看
以java中java.lang.System类中的一个得到系统当前时间的native方法为例,对native关键字进行说明:
__________________________________________________________
public final class System {//final关键字修饰的类不能被继承
.......
/**
*返回系统当前时间(该方法依赖于底层操作系统的实现)
*/
public static native long currentTimeMillis();
.......
}
__________________________________________________________
对于上面的currentTimeMillis();声明为native 表明:该方法的具体实现是依赖于底层的操作系统平台,并非java语言实现。
所以,一个native方法就是java调用非java代码的接口,当在方法中调用一些不是由java语言写的代码或者在方法中用java语言
直接操纵计算机硬件时要声明为native方法。native 方法中除了不能和abstract关键字连用(abstract表示方法是空实现,这显然与native调用外部实现的事实不符),非native方法并无区别。
---
JAVA本地方法适用的情况
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
----------------------------------------
类首次被使用到时,编译生成字节码会被加载到内存。在该字节码的入口维持着一个该类所有方法描述符的列表,这些方法描述符包含了类的详细信息。对应native方法,描述符块中会有一个指向该方法的实现的指针。这些实现在一些DLL文件(动态链接库文件dll是由java类编译后的.h文件及jni.h文件信息和具体的方法实现等编译生成的)内,当native方法被调用时,java会调用System.loadLibrary(*.dll)方法加载该dll。
其中,java通过javah(Javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件)生成该类的.h文件。
jni(Java Native Interface,java本地接口)
------------------------------------------下面是加载dll文件的具体实现-------
Java代码
/**
*java.lang.System中, 加载由 libname 参数指定的系统库
*/
public static
void loadLibrary(String libname) {//调用Runtime的loadLibrary方法
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}
/**
*Runtime的loadLibrary方法(带有synchronized的同步方法)
*/
synchronized void loadLibrary0(Class fromClass, String libname) {
//用于判断libname所指定文件的合法性
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkLink(libname);
}
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
}
//调用ClassLoader的loadLibrary方法
ClassLoader.loadLibrary(fromClass, libname, false);
}
/**
*ClassLoader的loadLibrary方法
*/
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute) {
try {
if (!DownloadManager.isJREComplete() &&
!DownloadManager.isCurrentThreadDownloading()) {
DownloadManager.downloadFile("bin/" + System.mapLibraryName(name));
}
} catch (Exception e) {
throw new UnsatisfiedLinkError("Error downloading library "
+ name + ": " + e);
}
ClassLoader loader = (fromClass == null) ?
null : fromClass.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
}
.......
}
另外,java.lang.System还用到了java中的另外两个比较常见的关键字:final和static。
在这里也做简单的说明:
关于final:
final修饰的类(比如System)表示该类不可被继承,所以final不能修饰interface或abstract类;
final修饰的方法不能被子类覆盖(不能被Override),不能修饰构造函数;
final修饰字段属性、参数时表示其被第一次赋值后不能被修改(但这里请注意,如果是一个对象,
不能修改的是该对象的引用,但是对象的内容还是可以修改的)
使用final的 好处:
1.防止被修改;2.final类型的方法被调用时,编译器会把它嵌入进来在一定程度上会提高了编译效率(注意是:一定程度,原因如下)。
编译器有一种被称为inline的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。
---------
关于static:
static 可以理解为“类”级别的关键字,因此对于static不存在this的概念,当类被jvm加载时,会按照声明的先后对static成员字段进行初始化
于是,static 可用于定义全局变量,而 static final 就可以定义一个常量
__________________________________________________________
public final class System {//final关键字修饰的类不能被继承
.......
/**
*返回系统当前时间(该方法依赖于底层操作系统的实现)
*/
public static native long currentTimeMillis();
.......
}
__________________________________________________________
对于上面的currentTimeMillis();声明为native 表明:该方法的具体实现是依赖于底层的操作系统平台,并非java语言实现。
所以,一个native方法就是java调用非java代码的接口,当在方法中调用一些不是由java语言写的代码或者在方法中用java语言
直接操纵计算机硬件时要声明为native方法。native 方法中除了不能和abstract关键字连用(abstract表示方法是空实现,这显然与native调用外部实现的事实不符),非native方法并无区别。
---
JAVA本地方法适用的情况
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
----------------------------------------
类首次被使用到时,编译生成字节码会被加载到内存。在该字节码的入口维持着一个该类所有方法描述符的列表,这些方法描述符包含了类的详细信息。对应native方法,描述符块中会有一个指向该方法的实现的指针。这些实现在一些DLL文件(动态链接库文件dll是由java类编译后的.h文件及jni.h文件信息和具体的方法实现等编译生成的)内,当native方法被调用时,java会调用System.loadLibrary(*.dll)方法加载该dll。
其中,java通过javah(Javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件)生成该类的.h文件。
jni(Java Native Interface,java本地接口)
------------------------------------------下面是加载dll文件的具体实现-------
Java代码
/**
*java.lang.System中, 加载由 libname 参数指定的系统库
*/
public static
void loadLibrary(String libname) {//调用Runtime的loadLibrary方法
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}
/**
*Runtime的loadLibrary方法(带有synchronized的同步方法)
*/
synchronized void loadLibrary0(Class fromClass, String libname) {
//用于判断libname所指定文件的合法性
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkLink(libname);
}
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
}
//调用ClassLoader的loadLibrary方法
ClassLoader.loadLibrary(fromClass, libname, false);
}
/**
*ClassLoader的loadLibrary方法
*/
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute) {
try {
if (!DownloadManager.isJREComplete() &&
!DownloadManager.isCurrentThreadDownloading()) {
DownloadManager.downloadFile("bin/" + System.mapLibraryName(name));
}
} catch (Exception e) {
throw new UnsatisfiedLinkError("Error downloading library "
+ name + ": " + e);
}
ClassLoader loader = (fromClass == null) ?
null : fromClass.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
}
.......
}
/** *java.lang.System中, 加载由 libname 参数指定的系统库 */ public static void loadLibrary(String libname) {//调用Runtime的loadLibrary方法 Runtime.getRuntime().loadLibrary0(getCallerClass(), libname); } /** *Runtime的loadLibrary方法(带有synchronized的同步方法) */ synchronized void loadLibrary0(Class fromClass, String libname) { //用于判断libname所指定文件的合法性 SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkLink(libname); } if (libname.indexOf((int)File.separatorChar) != -1) { throw new UnsatisfiedLinkError( "Directory separator should not appear in library name: " + libname); } //调用ClassLoader的loadLibrary方法 ClassLoader.loadLibrary(fromClass, libname, false); } /** *ClassLoader的loadLibrary方法 */ // Invoked in the java.lang.Runtime class to implement load and loadLibrary. static void loadLibrary(Class fromClass, String name, boolean isAbsolute) { try { if (!DownloadManager.isJREComplete() && !DownloadManager.isCurrentThreadDownloading()) { DownloadManager.downloadFile("bin/" + System.mapLibraryName(name)); } } catch (Exception e) { throw new UnsatisfiedLinkError("Error downloading library " + name + ": " + e); } ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); if (sys_paths == null) { usr_paths = initializePath("java.library.path"); sys_paths = initializePath("sun.boot.library.path"); } } ....... }--------------------------------------------------------------------------------------------------------------------------------
另外,java.lang.System还用到了java中的另外两个比较常见的关键字:final和static。
在这里也做简单的说明:
关于final:
final修饰的类(比如System)表示该类不可被继承,所以final不能修饰interface或abstract类;
final修饰的方法不能被子类覆盖(不能被Override),不能修饰构造函数;
final修饰字段属性、参数时表示其被第一次赋值后不能被修改(但这里请注意,如果是一个对象,
不能修改的是该对象的引用,但是对象的内容还是可以修改的)
使用final的 好处:
1.防止被修改;2.final类型的方法被调用时,编译器会把它嵌入进来在一定程度上会提高了编译效率(注意是:一定程度,原因如下)。
编译器有一种被称为inline的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。
---------
关于static:
static 可以理解为“类”级别的关键字,因此对于static不存在this的概念,当类被jvm加载时,会按照声明的先后对static成员字段进行初始化
于是,static 可用于定义全局变量,而 static final 就可以定义一个常量
相关文章推荐
- JAVA调用固有方法---native关键字
- Java Native调用C方法
- java native关键字方法
- JAVA中native方法调用
- JavaScript中模拟实现类似于Java的super关键字调用父类中同名方法
- java native interface(java 本地方法调用)
- native 调用 java 类中的一个静态方法
- java中的native关键字有什么作用?(java本地方法)
- Java中native方法(实现对类似C函数库的调用)
- Java方法关键字——native
- java native:Java本地方法调用(jni方式)
- 重写父类方法、super关键字、调用父类构造器——Java
- Mac下Java的native方法以及JNI调用C语言
- Java中包与包之间方法的调用及其关键字区分(基础)
- native应用 在C中调用JAVA的方法
- JNI中的各种函数对照表 方法调用对照表------java----jni-----native---方便查询
- java native interface JNI 调用Java方法
- JAVA JNI配置教程 使用JAVA调用Native方法打印Hello World
- Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API
- Java super关键字调用父类的方法疑惑