Java调用elasticsearch本地代码的操作方法
虽然Java虚拟机为开发人员屏蔽了底层的实现细节,使得开发人员不用考虑底层操作系统的差异性。不过在某些应用程序中,还是免不了要直接与底层操作系统上的原生代码进行交互。今天我们就来看一下Java对本地调用提供的支持。
一、为什么要进行本地调用
1.基于性能的考虑
Java语言从其运行速度上来说,在大多数方面是慢于底层操作系统上原生的C和C++等语言的。这主要是由于Java虚拟机这个中间层次的存在。如果完全用Java语言实现的性能无法达到程序的预期要求,可以选择把部分重要且耗时的代码用C或C++来实现。
2.基于某些特殊的需求
Java平台提供的标准类库的功能很强大,包括了在开发中可能遇到的大部分功能。但是仍然有一些功能无法用标准API来实现,主要是一些与底层硬件平台直接交互的功能。Java虚拟机没有把这一部分功能暴露给运行在其上的程序。如果需要这方面的功能,那么只能使用原生代码来进行开发。
3.与已有的使用原生代码编写的程序之间进行集成。
如果Java程序需要与底层操作系统上由C和C++语言开发的程序进行交互,那么可以进行本地调用。
我们平时的开发更多的情况是后边两种情况;在elasticsearch中基本上是属于第二种情况。
二、使用JNI实现本地调用
针对以上提到的各种情况,Java提供了JNI(Java Native Interface)和JNA(Java Native Access)两种方式,其中JNI的一个重要使用场景是提高程序的性能。当对程序中关键部分的性能要求比较高的时候,可以使用C和C++代码来实现。
我们先来看下怎么使用JNI来进行本地调用。
首先我们需要有一个Java类来声明本地方法,并负责加载本地代码库。本地方法与Java接口中的方法或抽象类中的抽象方法一样,只包含方法声明,没有相关的实现。程序中的其他部分可以用正常的方法调用本地方法,比如参数传递和返回值使用等都与正常的方法相同。当虚拟机在执行本地方法时,会尝试在已经加载的本地代码库中查找本地方法的对应实现。在查找到对应的实现方法之后,虚拟机会负责进行参数传递、实际方法调用和返回值传递等工作。
public class HelloNative { static{ System.loadLibrary("greetLib"); } public static native void greeting(); }
下一步要编写实现本地方法的C/C++代码。Java提供的命令行工具根据Java源代码生成C/C++代码所需的头文件。对于本地方法,头文件中会包含相关的方法声明与其对应。
F:\source\JNI\src>javac -h .\ .\HelloNative.java
通过下边自动生成的头文件,我们可以看到这里有很多的隐式约定,我们只要按照这个声明进行实现即可,具体的规则不是今天的重点,不进行详述。
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloNative */ #ifndef _Included_HelloNative #define _Included_HelloNative #ifdef __cplusplus extern "C" { #endif /* * Class: HelloNative * Method: greeting * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloNative_greeting (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
三、elasticsearch使用JNA实现本地调用
通过上边对JNI的简单了解,我们更多的时候碰到的情况是,在编写Java程序之前,就已经有了可以使用的本地代码库。这个本地代码库可能是程序的一部分,也可能是底层操作系统自带的。这些本地代码库的特点是在实现的时候并没有考虑与Java虚拟机的集成,因此也没有使用与JNI相关的内容。在使用这样的本地代码库时,我们就需要一个中间的本地代码库作为桥梁。这个本地代码库作为Java程序中本地方法的实现,负责实际调用时的参数类型转换和返回值传递等工作。这个过程是十分的繁琐的,Java提供了JNA来支持这种情况。
我们知道elasticsearch启动的时候需要检测当前用户是否是root用户,这个检测是直接调用的底层操作系统的代码,我们来看下elasticsearch是怎样使用JNA实现的。
首先elasticsearch提供了Natives类,作为调用本地方法的入口,并负责检测JNA的可用性。
static { boolean v = false; try { // load one of the main JNA classes to see if the classes are available. this does not ensure that all native // libraries are available, only the ones necessary by JNA to function Class.forName("com.sun.jna.Native"); v = true; } catch (ClassNotFoundException e) { logger.warn("JNA not found. native methods will be disabled.", e); } catch (UnsatisfiedLinkError e) { logger.warn("unable to load JNA native support library, native methods will be disabled.", e); } JNA_AVAILABLE = v; }
检测JNA是否可用,然后再调用JNANatives的对用方法
static boolean definitelyRunningAsRoot() { if (!JNA_AVAILABLE) { logger.warn("cannot check if running as root because JNA is not available"); return false; } return JNANatives.definitelyRunningAsRoot(); }
在JNANatives的definitelyRunningAsRoot中,如果是非windows系统,则调用
JNACLibrary.geteuid
/** Returns true if user is root, false if not, or if we don't know */ static boolean definitelyRunningAsRoot() { if (Constants.WINDOWS) { return false; // don't know } try { return JNACLibrary.geteuid() == 0; } catch (UnsatisfiedLinkError e) { // this will have already been logged by Kernel32Library, no need to repeat it return false; } }
elasticsearch使用JNAKernel32Library来封装对windows的Kernel32的调用,使用 JNACLibrary来封装对非windows系统的libc的调用
static { try { Native.register("c"); } catch (UnsatisfiedLinkError e) { logger.warn("unable to link C library. native methods (mlockall) will be disabled.", e); } } static native int mlockall(int flags); static native int geteuid();
四、总结
JNI更适合使用本地调用来解决对性能有更高要求的场景,需要我们自己使用C或者C++来实现处理逻辑。对于调用已有的本地库的方法或者操作系统的方法,使用JNA更为方便便捷。
到此这篇关于Java调用elasticsearch本地代码的文章就介绍到这了,更多相关Java调用elasticsearch内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了Spring AOP 对象内部方法间的嵌套调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- <?php require('path.inc.php'); header('content-Type: text/html; charset=utf-8'); $borough_id = intval($_GET['id']); if(!$borough_id){ echo ' ...2016-11-25
- 这篇文章主要介绍了c# 三种方法调用WebService接口的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-07
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了js实现调用网络摄像头及常见错误处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-07
- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
- 这篇文章介绍了c#动态调用Webservice的两种方法实例,有需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
Elasticsearch工具cerebro的安装与使用教程
这篇文章主要介绍了Elasticsearch工具cerebro的安装与使用教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-08