乐趣区

关于java:Java基础-native关键字是干什么用的

[TOC]
明天一不小心跟进 Object 的源码中,发现一个 native 关键字,一脸蒙蔽,怎么我素来没有用过。

// 这是计算对象的 hsahcode 的办法,波及到内存地址
public native int hashCode();

1. 汇编生 c,c 生万物, 其实 java 要实现对底层的管制,还是须要 c/c++ 帮忙,老大毕竟是老大。

2.native关键字咱们开发利用的时候是用不到的,那什么时候用到呢?那些开发 java 语言 的时候用到,native关键字是与 c++ 联合开发的时候应用的,要不 java 控制不了底层啊,比方内存。所以还是那句:汇编生 c,c 生万物,c++c 的升级版。

3. 这是 java 调用其余中央的接口的一个申明关键字,意思是这个办法不是 java 实现的, 有挺多的编程语言都有这样的个性,比方 c++ 外面应用 extern "c" 来示意通知 c ++ 编译器去调用 c 外面曾经实现好的函数,而不是本人去实现。native办法有点像 java 外面的interface,都不必去实现,而是有他人去实现,然而interface 是谁实现接口谁实现,native办法是间接交给 c/c++ 来实现。java只能调用,由操作系统实现。

4.native办法不能与 abstract 办法一起应用,因为 native 示意这些办法是有实现体的,然而 abstract 却示意这些办法是没有实现体的,那么两者矛盾,必定也不能一起应用。

1. 怎么调用到 native 办法的呢?

下面说 native 示意这个办法不是 java 实现的,那么就不是原生态办法,也就不会存在这个文件中,而是存在其余中央,那么 java 要怎么调用能力调用到呢?

  • JNI(Java Native Interface)这是一个本机编程的接口,它也是 java jdk(开发工具包)的一部分,JNI 能够反对 java 中应用其余语言,java 要调用其余语言的接口,须要通过他解决。java 所谓的跨平台,在肯定水平上放弃了底层操作,因为不同的硬件或者操作系统底层的操作都是不一样的。

那么咱们当初来写一个程序:helloWorld.java(我的所有写的文件都放在桌面,同个文件夹即可)

public class helloworld{
  static
  {System.loadLibrary("cSayHello");
  }
  public static native void hello();
  @SuppressWarnings("static-access")
  public static void main(String[] args){new helloworld().hello();}
}

间接在编译器运行这段代码会呈现上面谬误:

下面的谬误是说找不到 cSayHello:no cSayHello in java.library.path, 所以啊,这个c/c++ 的办法咱们要本人实现,毕竟咱们用的不是操作系统以及定义好的办法。
所以咱们先来,应用 cmd 在 helloworld.java 所在的目录下 应用命令行:

javac helloworld
javah helloworld

而后咱们能够看到 在 helloworld.java 所在的目录下 多了两个文件,一个是 helloworld.class 文件, 一个是 helloworld.h 文件。

关上 helloworld.h, 外面援用了jni.h 这个文件,这个文件在咱们装置的 java 目录上面的 include 文件下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class helloworld */

#ifndef _Included_helloworld
#define _Included_helloworld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     helloworld
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_helloworld_hello
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

我的 java 是装在 D 盘 上面:

咱们来写须要引入的 c 文件cSayHello, 我也是放在桌面,反正同一个文件夹就能够。

#include "helloworld.h"
#include <stdio.h>
 
JNIEXPORT void JNICALL Java_helloworld_hello(JNIEnv *env, jclass jc)
{printf("java helloworld");    
}

windows 零碎上,须要下载安装 WinGW Gcc,装置教程参考 https://www.jianshu.com/p/535… 装置胜利cmd 输出:

gcc -m64  -Wl,--add-stdcall-alias -I"D:\Java\jdk1.8.0_111\include" -I"D:\Java\jdk1.8.0_111\include\win32" -shared -o cSayHello.dll helloworld.c

而后间接运行, 就能够看到输入了

java helloworld

2. java 调用自定义 native 办法步骤

在 java 中应用 native 的步骤:
1. 在 java 代码中申明 native 办法
2. 执行 javah 来生成一个.h 文件
3. 写.cpp 文件来实现 native 导出的办法,须要蕴含下面第二步产生的.h 文件,同时也蕴含了 jdk 自带的 jni.h
4. 将第三步的.cpp 文件通过 gcc 编译成动态链接库文件
5. 在 java 中应用的用 System.loadLibrary()办法加载第四步产生的动态链接库文件,这个 native()办法就能够在 Java 中被拜访
个别状况下,咱们 jdk 中申明的 native 办法,在编译的时候都会主动去加载动态链接库文件,而不须要咱们本人去操作了。

3. 应用 native 的毛病

应用 native 的毛病:可移植性差,把对底层的控制权交给其余语言,那么也会呈现不稳定性,庆幸的是当初操作系统的底层实现根本不会扭转。下面 hsahcode()的计算真是通过内存所在的内存块来计算的,java 是无奈间接操作内存的。

【作者简介】
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使迟缓,驰而不息。这个世界心愿所有都很快,更快,然而我心愿本人能走好每一步,写好每一篇文章,期待和你们一起交换。

此文章仅代表本人(本菜鸟)学习积攒记录,或者学习笔记,如有侵权,请分割作者核实删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有谬误之处,还望指出,感激不尽~

退出移动版