【JVM之内存与垃圾回收篇】本地方法接口
本地方法接口
什么是本地方法
简单地讲,一个 Native Method 是一个 Java 调用非 Java 代码的接囗。一个 Native Method 是这样一个 Java 方法:该方法的实现由非 Java 语言实现,比如 C。这个特征并非 Java 所特有,很多其它的编程语言都有这一机制,比如在 C++ 中,你可以用 extern "c" 告知 C++ 编译器去调用一个 C 的函数。
"A native method is a Java method whose implementation is provided by non-java code."(本地方法是一个非 Java 的方法,它的具体实现是非 Java 代码的实现)
在定义一个 native method 时,并不提供实现体(有些像定义一个 Java interface),因为其实现体是由非 java 语言在外面实现的。
本地接口的作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++ 程序。

代码举例说明 Native 方法是如何编写的
/**
* 本地方法
*
* @author: Nemo
*/
public class IhaveNatives {
public native void Native1(int x);
native static public long Native2();
native synchronized private float Native3(Object o);
native void Natives(int[] ary) throws Exception;
}
需要注意的是:标识符native可以与其它java标识符连用,但是abstract除外
为什么使用 Native Method?
Java 使用起来非常方便,然而有些层次的任务用 Java 实现起来不容易,或者我们对程序的效率很在意时,问题就来了。
与 Java 环境的交互
有时 Java 应用需要与 Java 外面的环境交互,这是本地方法存在的主要原因。你可以想想 Java 需要与一些底层系统,如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解 Java 应用之外的繁琐的细节。
与操作系统的交互
JVM 支持着 Java 语言本身和运行时库,它是 Java 程序赖以生存的平台,它由一个解释器(解释字节码)和一些连接到本地代码的库组成。然而不管怎样,它毕竟不是一个完整的系统,它经常依赖于一底层系统的支持。这些底层系统常常是强大的操作系统。通过使用本地方法,我们得以用 Java 实现了 jre 的与底层系统的交互,甚至 JVM 的一些部分就是用 C 写的。还有,如果我们要使用一些 Java 语言本身没有提供封装的操作系统的特性时,我们也需要使用本地方法。
Sun's Java
Sun 的解释器是用 C 实现的,这使得它能像一些普通的 C 一样与外部交互。jre 大部分是用 Java 实现的,它也通过一些本地方法与外界交互。例如:类 java.lang.Thread 的 setPriority() 方法是用 Java 实现的,但是它实现调用的是该类里的本地方法 setPriority()。这个本地方法是用 C 实现的,并被植入 JVM 内部,在 Windows 95 的平台上,这个本地方法最终将调用 Win32 setPriority() API。这是一个本地方法的具体实现由 JVM 直接提供,更多的情况是本地方法由外部的动态链接库(external dynamic link library)提供,然后被 JVW 调用。
注意:标识符 native 可以与所有其他的 Java 标识符连用,但是 abstract 除外。
现状
目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过 Java 程序驱动打印机或者 Java 系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用 Socket 通信,也可以使用 Web Service 等等,不多做介绍。
Java如何调用C语言程序,JNI技术
Java为什么要调用C语言编写的程序
因为涉及操作系统底层的事件,Java是处理不了的,例如用户上传一个视频文件,需要后台给视频加上水印,或者后台分离视频流和音频流,这个事Java就做不了,只能交给C语言去处理,然后Java调用C语言的接口。
使用Java如何去调用C语言的接口呢?
使用Java的JNI技术。
具体调用步骤
CentOS7环境下
首先创建Java文件 HelloJni.java ,并创建native方法
package com.hongyu.jni;
public class HelloMyJni{
public native void helloWorld(); // 注意,这个native方法就是调用C语言接口用的
static{
System.loadLibrary("hello"); // 这行是调用动态链接库
}
public static void main(String[] args){
new HelloMyJni().helloWorld();
}
}
编译Java文件并生成java头文件
javac -d . HelloJni.java // 生成class文件
javah -jni com.hongyu.jni.HelloJni // 生成java头文件 com_hongyu_jni_HelloJni.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_hongyu_jni_HelloJni */
#ifndef _Included_com_hongyu_jni_HelloJni
#define _Included_com_hongyu_jni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_hongyu_jni_HelloJni
* Method: helloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_hongyu_jni_HelloJni_helloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
创建C语言文件,HelloWorld.c
#include "jni.h"
#include "com_hongyu_jni_HelloJni.h"
#include <stdio.h>
#include <stdlib.h>
JNIEXPORT void JNICALL Java_com_hongyu_jni_HelloJni_helloWorld(JNIEnv * env, jobject obj)
{
printf("Hello World!\n");
}
生成动态链接库文件 libhello.so
#gcc -Wall -fPIC -c HelloWorld.c -I ./ -I $JAVA_HOME/include/linux/ -I $JAVA_HOME/include/
#gcc -Wall -rdynamic -shared -o libhello.so HelloWorld.o
设置动态链接库文件的目录
打开文件
vi ~/.bash_profile
修改文件:
export JAVA_HOME=/home/jdk1.8.0_161
export PATH=$JAVA_HOME/bin:$PATH
export LD_LIBRARY_PATH=/home/lib:$LD_LIBRARY_PATH
刷新文件:
source ~/.bash_profile
把刚才生成的so文件拷贝到/home/lib下,然后执行class文件
java com.hongyu.jni.HelloJni
大功告成!Java成功调用了C语言编写的逻辑
【JVM之内存与垃圾回收篇】本地方法接口的更多相关文章
- 【JVM之内存与垃圾回收篇】方法区
方法区 前言 这次所讲述的是运行时数据区的最后一个部分 从线程共享与否的角度来看 ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理,以及会话管理 栈.堆.方法区 ...
- 【JVM之内存与垃圾回收篇】虚拟机栈
虚拟机栈 虚拟机栈概述 由于跨平台性的设计,Java 的指令都是根据栈来设计的.不同平台 CPU 架构不同,所以不能设计为基于寄存器的. 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同 ...
- 【JVM之内存与垃圾回收篇】JVM与Java体系结构
JVM与Java体系结构 前言 作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问题? 运行着的线上系统突然卡死,系统无法访问,甚至直接OOMM! 想解决线上JVM GC问题,但却无从下手. 新 ...
- 【JVM之内存与垃圾回收篇】运行时数据区概述及线程
运行时数据区概述及线程 前言 本节主要讲的是运行时数据区,也就是下图这部分,它是在类加载完成后的阶段 当我们通过前面的:类的加载-> 验证 -> 准备 -> 解析 -> 初始化 ...
- 【JVM之内存与垃圾回收篇】堆
堆 堆的核心概念 堆针对一个 JVM 进程来说是唯一的,也就是一个进程只有一个 JVM,但是进程包含多个线程,他们是共享同一堆空间的. 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的 ...
- 【JVM之内存与垃圾回收篇】对象实例化内存布局与访问定位
对象实例化内存布局与访问定位 从各自具体的内存分配上来讲 new 的对象放在堆中 对象所属的类型信息是放在方法区的 方法当中的局部变量放在栈空间 这 new 的对象怎么把三块粘合到一起 就是这章的内容 ...
- 【JVM之内存与垃圾回收篇】StringTable
StringTable String的基本特性 String:字符串,使用一对 "" 引起来表示 String s1 = "Nemo"; // 字面量的定义方式 ...
- 【JVM之内存与垃圾回收篇】类加载子系统
类加载子系统 概述 完整图如下: 如果自己想手写一个 Java 虚拟机的话,主要考虑哪些结构呢? 类加载器 执行引擎 类加载器子系统作用 类加载器子系统负责从文件系统或者网络中加载 Class 文件, ...
- 【JVM之内存与垃圾回收篇】执行引擎
执行引擎 执行引擎概述 执行引擎属于 JVM 的下层,里面包括 解释器.及时编译器.垃圾回收器 执行引擎是 Java 虚拟机核心的组成部分之一. "虚拟机"是一个相对于" ...
- 【JVM之内存与垃圾回收篇】程序计数器
程序计数器 介绍 JVM 中的程序计数寄存器(Program Counter Register)中,Register 的命名源于 CPU 的寄存器,寄存器存储指令相关的现场信息.CPU 只有把数据装载 ...
随机推荐
- JuiceFS 2024:开源与商业并进,迈向 AI 原生时代
即将过去的 2024 年,是 JuiceFS 开源版本推出的第 4 年,企业版的第 8 个年头.回顾过去这一年,JuiceFS 社区版依旧保持着快速成长的势头,GitHub 星标突破 11.1K,各项 ...
- 在OERV也可以玩MC(上)
最近发现一个比较有意思的事情,原来HMCL这个项目也移植到RISC-V上了,之前一直没有发现,因此在OERV(openEuler RISC-V的简称)玩MC也是可以的了.首先,HMCL是一款功能丰富的 ...
- w3cschool-Apache Storm 教程
https://www.w3cschool.cn/apache_storm/ Apache Storm教程Apache Storm简介Apache Storm核心概念Apache Storm集群架构A ...
- biancheng-MySQL教程
目录http://c.biancheng.net/mysql/ 1数据库入门2MySQL的安装和配置3MySQL数据库的基本操作4数据库设计5MySQL数据类型和存储引擎6MySQL数据表的基本操作7 ...
- Kotlin:【set集合】集合创建、可变集合mutableSetOf、集合转换(List转换成Set,去掉重复元素)、distinct快捷去重函数、数组
- Exfiltrated pg walkthrough Easy
80端口弱口令admin admin 发现cms 搜索exp 发现漏洞 https://www.exploit-db.com/exploits/49876 找到敏感数据库密码和用户 ╔════════ ...
- 调试存储过程中出现 [Microsoft][ODBC SQL Server Driver]对于造型说明无效的字符值
调试存储时如果有日期类型的参数,传入格式为:2020-07-13 12:00:00 ,无需用引号括起来. 否则会提示[Microsoft][ODBC SQL Server Driver]对于造型说明无 ...
- 首批!天翼云率先通过ITU国际标准认证!
近日,天翼云通过国内唯一人工智能云平台领域的ITU国际标准评估--中国信通院组织的ITU-T F.AICP-GA人工智能云平台技术规范国际标准和<智算工程平台能力要求>国内标准一致性评估, ...
- nginx 编译安装及配置解析
一.编译安装 安装插件 安装需要的组件 yum -y install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel ...
- 使用VS Code开发微信小程序
.MathJax, .MathJax_Message, .MathJax_Preview { display: none } 使用VS Code开发微信小程序 微信开发工具 结构 缺点 VS Code ...