Java调用linux shell命令的时候,是通过Process来实现的,Process会新起一个进程,并且把主进程的内存信息拷贝一份到新的进程中,对于小的程序这种方式没问题,但如果项目足够大,就会导致系统内存不够程序退出的情况发生。
为了解决这个问题,有一个比较好的方案是JNI,这个时候并不需要重新起一个Process,也就不会存在备份内存的问题,下面是一个例子.
1.编写java类JNIHelper.java
package com.pracbiz;
public class JNIHelper
{
static
{
System.loadLibrary("JNI");
}
public native String exec(String input);
private static JNIHelper instance;
private JNIHelper()
{
}
public static JNIHelper getInstance()
{
synchronized(JNIHelper.class)
{
if(instance == null)
{
instance = new JNIHelper();
}
}
return instance;
}
public static void main(String[] args)
{
getInstance().exec("pwd");
}
}
2.通过jdk自带的javah命令生成c头文件com_pracbiz_JNIHelper.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_pracbiz_JNIHelper */
#ifndef _Included_com_pracbiz_JNIHelper
#define _Included_com_pracbiz_JNIHelper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_pracbiz_JNIHelper
* Method: exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_pracbiz_JNIHelper_exec
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
3.编写c++文件,实现头文件中的方法com_pracbiz_JNIHelper.cpp
#include "com_pracbiz_JNIHelper.h"
#include <string.h>
#include <errno.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
JNIEXPORT jstring JNICALL Java_com_pracbiz_JNIHelper_exec
(JNIEnv *env, jobject obj, jstring input)
{
std::string result;
std::string cmd;
FILE *fstream=NULL;
char buff[1024]="";
char const *str = (char *)env->GetStringUTFChars(input, NULL);
char const *ext = " 2>&1";
cmd.append(str);
cmd.append(ext);
memset(buff,0,sizeof(buff));
if(NULL==(fstream=popen(cmd.c_str(),"r")))
{
fprintf(stderr,"execute command failed: %s",strerror(errno));
env->ReleaseStringUTFChars(input, str);
return env->NewStringUTF("-1");
}
env->ReleaseStringUTFChars(input, str);
while (NULL!=fgets(buff, sizeof(buff), fstream))
{
result.append(buff);
}
if (fstream != NULL)
{
pclose(fstream);
}
return env->NewStringUTF(result.c_str());
}
int main()
{
return 0;
};
4.生成对应的jni可执行文件,注意命名格式,linux结尾为.so, mac os结尾为.jnilib
linux:
gcc -Wall -fPIC -I./ -I/opt/jdk1.6.0_32/include -I/opt/jdk1.6.0_32/include/linux -shared -o libJNI.so com_pracbiz_JNIHelper.cpp -lstdc++
mac os:
gcc -Wall -fPIC -I./ -I/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers -shared -o libJNI.jnilib com_pracbiz_JNIHelper.cpp -lstdc++
-l是编译时的路径参数,编译JNI文件需要两个java提供的库文件,jni.h和jni_md.h,对于linux, jni.h在opt/jdk1.6.0_32/include, jni_md.h存在/opt/jdk1.6.0_32/include/linux, 对于mac os来说,这两个文件都在 /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers目录下,不同的linux发行版以及不同的jdk版本可能位置会有所不同,这个在编译之前自己去确认下两个文件的路径。
5.文件生成好以后需要放到java.library.path,这样jvm才能加载到,那这个目录是什么呢,通过System.getProperty("java.library.path")方法就可以得到.
或者可以通过-Djava.library.path指定也行,下面会讲到。
6.应用很简单,写个TestJni.java,我是写在com.pracbiz.b2bportal.base.action包下面的.
system.out.println(JNIHelper.getInstance().exec("ls -la"));
以linux平台为例,如果so文件没有放到java.library.lib下,则运行时通过-Djava.library.path指定.so文件的路径
java -Djava.library.path=/home/oyl-admin/b2bportal/EC-Portal/branches/fp-phase2-client/web/WEB-INF/classes com.pracbiz.b2bportal.base.action.TestJni
如果已经放到java.library.lib下,则直接运行
java com.pracbiz.b2bportal.base.action.TestJni
分享到:
相关推荐
在这个"第一个JNI实例学习"中,我们将探讨如何创建并运行一个基本的JNI程序。 首先,我们需要理解JNI的核心概念。JNI提供了一套接口,让Java代码能够声明本地方法,这些方法在运行时由本地(非Java)代码实现。本地...
我们将以"android调用JNI实例"为例,一步步解释这个过程。 首先,我们需要准备开发环境。安装Android NDK是必不可少的步骤,NDK(Native Development Kit)是一组工具,开发者可以使用它来编写用C和C++编写的本地...
本实例是基于Eclipse的JNI应用,已经过测试,能够帮助开发者直观地理解JNI的调用流程。 首先,我们来详细了解一下JNI的基本概念。JNI提供了一种方式,让Java代码可以调用本地(非Java)代码,也可以让本地代码调用...
本篇文章将深入探讨JNI实例的使用,包括基本的设置、回调机制、传递Java集合如Map到本地方法以及处理复杂对象。 首先,让我们理解JNI的基本工作原理。JNI的核心是定义了一套Java到本地代码(如C/C++)的调用规范。...
本教程将深入探讨Linux环境下的JNI实例以及JNI编程模板。 1. JNI基础: JNI提供了一种标准方式,让Java虚拟机(JVM)能够调用本地方法(即非Java语言编写的函数)。本地方法通常用C或C++编写,可以充分利用硬件...
这个“简单的JNI实例”显然是为了帮助初学者理解和掌握JNI的基本用法。 JNI的核心概念主要包括以下几个部分: 1. **本地方法接口**:JNI定义了一组函数,这些函数在Java虚拟机(JVM)内部实现,允许Java代码调用...
在这个“Android JNI实例01”中,我们将探讨如何使用JNI在Android应用中集成C/C++代码,以及如何在ARM架构的设备上运行这些本地代码。 1. **JNI基础**: - JNI接口定义了一系列函数,如`FindClass`, `GetMethodID`...
总结来说,这个“简单JNI实例调用第三方.so库”的例子展示了如何在Java应用程序中通过JNI调用C/C++代码。这个过程包括:定义Java的native方法、使用javah生成C/C++头文件、编写C/C++实现、编译生成.so库以及在Java...
**配置NDK集成Eclipse使用hello-jni实例步骤** 1. **安装Cygwin** - 访问Cygwin官方网站下载安装包,并在Windows上解压。 - 在安装过程中,选择合适的安装路径,避免包含空格和中文字符,以防止可能出现的问题。 ...
在Android开发中,NDK(Native Development...总之,"ndk jni实例源码"提供了一个基础的Android原生开发教程,通过学习和实践,开发者可以掌握在Android应用中使用C/C++代码的关键步骤,为更复杂的系统级开发打下基础。
总之,JNI实例“Java调用DLL c++调用Java”是一个实用的学习资源,它详细解释了如何利用JNI进行Java与C++的交互,无论是将本地库引入Java程序还是将Java功能嵌入C++应用。通过实践这些例子,开发者能够深入理解JNI的...
通过这个纯C版本的JNI实例,初学者可以深入了解JNI的工作原理,如何在C代码中操作Java对象,以及如何在Java和本地代码之间传递数据。同时,它也演示了如何在不同的开发环境中(如Cgwin)进行编译和链接。
在本例中,我们看到一个JNI实例的演示,它涉及到在Java程序中调用C/C++编写的本地方法。 首先,我们有一个名为`Student`的Java类,它包含了学生的基本信息,如姓名(`name`)和年龄(`age`)。这个类有对应的getter...
在这个"Mstar平台JNI实例"中,我们将探讨如何在Android环境中使用JNI技术实现特定的功能,如个人资料备份,并且通过了验证测试。 首先,理解JNI的基本概念是至关重要的。JNI为Java应用程序提供了一种方式,使得Java...
本实例提供了一个使用JNI调用C++ DLL(动态链接库)的示例,对于学习和理解JNI的工作原理及其应用非常有帮助。 首先,我们来了解JNI的基本概念。JNI包含了一组头文件和库,它们定义了Java虚拟机(JVM)与本地代码...
总的来说,Android JNI实例涵盖了从Java到C/C++的调用过程,涉及了JNI的基本原理和实践技巧。无论是静态注册还是动态注册,都需要理解JNI的核心概念,如JNI函数的调用约定、JNI数据类型以及Java对象在本地代码中的...