首页 > 编程语言 >Java JNA、JNI、ProcessBuilder、Runtime.getRuntime.exec()详解

Java JNA、JNI、ProcessBuilder、Runtime.getRuntime.exec()详解

时间:2024-09-18 17:53:00浏览次数:11  
标签:Java ProcessBuilder exec int 代码 本地 JNI 交互

Java 提供了几种方式与非 Java 代码进行交互(比如调用本地库或执行外部程序),其中包括 JNA、JNI、ProcessBuilderRuntime.getRuntime().exec()。下面是对每种方式的详细解释。


1. JNA (Java Native Access)

简介

JNA 是 Java 与本地代码进行交互的一种高层次 API,它允许 Java 程序调用本地动态链接库(DLL 或 .so 文件)中的函数,而无需编写 JNI(Java Native Interface)代码。JNA 大大简化了与本地代码的交互,因为它自动处理了参数的转换、调用约定等复杂细节。

使用场景

  • 需要调用现有的本地库(如 C/C++ 编写的 DLL 或 .so)。
  • 不需要手动编写复杂的 JNI 代码。
  • 性能要求没有 JNI 那么高。

工作原理

JNA 使用动态代理模式,将 Java 方法映射到本地库函数。它依赖于 com.sun.jna.Native 类来加载本地库,并通过接口定义与本地库中的函数进行交互。

示例代码

假设有一个名为 mydll.dll 的 C 函数:

// mydll.c
int add(int a, int b) {
    return a + b;
}

在 Java 中通过 JNA 调用它:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class MyDllCaller {
    // 定义与DLL函数的接口
    public interface MyDll extends Library {
        MyDll INSTANCE = (MyDll) Native.load("mydll", MyDll.class);
        int add(int a, int b);
    }

    public static void main(String[] args) {
        int result = MyDll.INSTANCE.add(3, 4);
        System.out.println("Result: " + result);  // 输出 7
    }
}

优点

  • 简单易用,减少了手动处理本地库调用的复杂性。
  • 无需生成本地代码,直接通过接口与动态库交互。
  • 支持跨平台使用,动态加载库。

缺点

  • 性能相对比 JNI 稍低。
  • 不支持复杂的指针操作和本地数据结构的深度操作。

------------------------------------------------------------------------------------------------------------------------------

2. JNI (Java Native Interface)

简介

Java中传参并调用C++程序_java 调用c++ 传递参数-CSDN博客

JNI 是 Java 与本地代码(如 C/C++)交互的低层次接口。它允许 Java 直接调用 C/C++ 函数,或者将 C/C++ 代码嵌入到 Java 应用中。与 JNA 不同,JNI 需要编写本地代码,并且通过 JNI 的 API 来与 Java 进行交互。

使用场景

  • 对性能有严格要求,需要与本地代码进行高效交互。
  • 需要访问 Java 环境中的复杂数据结构,或需要在 C/C++ 中对 Java 对象进行操作。
  • 需要与不使用动态库的本地代码进行深度集成。

工作原理

  1. 编写 Java 代码声明本地方法。
  2. 使用 javah 生成 C/C++ 头文件。
  3. 编写与 Java 本地方法匹配的 C/C++ 实现。
  4. 使用 JNI API 与 JVM 进行交互。

示例代码

Java 代码:

public class MyJNI {
    // 声明本地方法
    public native int add(int a, int b);

    static {
        // 加载本地库
        System.loadLibrary("myjni");
    }

    public static void main(String[] args) {
        MyJNI jni = new MyJNI();
        int result = jni.add(3, 4);
        System.out.println("Result: " + result);  // 输出 7
    }
}

C/C++ 实现:

#include <jni.h>
#include "MyJNI.h"  // 生成的头文件

JNIEXPORT jint JNICALL Java_MyJNI_add(JNIEnv *env, jobject obj, jint a, jint b) {
    return a + b;
}

优点

  • 高性能,适合需要频繁调用本地代码的场景。
  • 灵活,可以访问和操作 Java 对象。
  • 完全控制,可以处理复杂的指针操作和数据结构。

缺点

  • 编写和维护 JNI 代码相对复杂,需要理解 JNI 的 API 以及 Java 和本地代码之间的内存管理。
  • 跨平台支持复杂,不同平台需要不同的本地库。
  • 调试难度大。

3. ProcessBuilder

简介

ProcessBuilder 是 Java 中用于创建和管理操作系统进程的类。它允许 Java 程序启动外部进程(如可执行文件、脚本等),并与该进程进行交互(如传递输入、读取输出、检查退出状态)。

使用场景

  • 需要从 Java 中运行外部程序(如 .exe 或脚本)。
  • 与外部工具或服务进行交互。
  • 对进程的启动、输入输出管理有较高的需求。

工作原理

ProcessBuilder 创建一个新的进程,并允许通过流(InputStream/OutputStream)与进程进行交互。

示例代码

import java.io.*;

public class ProcessBuilderExample {
    public static void main(String[] args) {
        try {
            // 使用 ProcessBuilder 运行命令
            ProcessBuilder builder = new ProcessBuilder("ping", "google.com");

            // 启动进程
            Process process = builder.start();

            // 读取进程的输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // 等待进程结束
            int exitCode = process.waitFor();
            System.out.println("Exit code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点

  • 提供了对进程的详细控制,包括重定向输入输出流。
  • 支持异步进程的管理(通过 Process.waitFor() 等方法)。
  • 简单易用,可以启动任何外部程序或脚本。

缺点

  • 对外部程序的依赖性强,外部程序的路径和可用性可能会有问题。
  • 进程之间的数据传输主要依赖于流,处理复杂的交互时可能会变得笨重。
  • 不适合高频调用外部程序的场景,启动进程的开销较大。

4. Runtime.getRuntime().exec()

简介

Runtime.getRuntime().exec()ProcessBuilder 的旧版本 API,也用于从 Java 程序中执行外部命令或程序。它可以启动外部进程并返回 Process 对象,用于与进程交互。

使用场景

  • 需要从 Java 中简单地运行一个外部命令或程序。
  • 不需要对进程有复杂的控制和管理要求。

工作原理

通过调用 Runtime.getRuntime() 获取当前 JVM 的运行时对象,然后调用其 exec() 方法启动外部进程。

示例代码

import java.io.*;

public class RuntimeExecExample {
    public static void main(String[] args) {
        try {
            // 执行外部命令
            Process process = Runtime.getRuntime().exec("ping google.com");

            // 读取输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // 等待进程结束
            int exitCode = process.waitFor();
            System.out.println("Exit code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点

  • 简单直接,可以快速执行命令。
  • 支持与操作系统的简单交互。

缺点

  • 功能不如 ProcessBuilder 强大,无法对输入输出重定向和环境变量进行详细控制。
  • 对于复杂的进程管理需求不够灵活。

标签:Java,ProcessBuilder,exec,int,代码,本地,JNI,交互
From: https://blog.csdn.net/m0_55049655/article/details/142336286

相关文章

  • java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not fo
    一、概述在AndroidStudio中集成opencv,使用其native函数时报的一个错误 二、解决办法opencv提供的native文件夹中提供的是动态库但是在gradle中的配置中,配置的stl是静态的,将其改为shared就行了externalNativeBuild{cmake{cp......
  • 准备好了吗?JAVA从业AI开发的学习路线详解
    作为一个拥有扎实Java基础的人,想要涉足人工智能(AI)应用开发,你已经在编程能力方面打下了很好的基础。Java是一种通用的、强类型的语言,非常适合于开发高性能的应用程序,尤其是在后端服务和大规模分布式系统方面。AI领域是一个高度跨学科的领域,涵盖了机器学习、深度学习、数据科学、......
  • 【他山之石】优化 JavaScript 的乐趣与价值(下)
    前言继本文的上篇发表之后,没想到反响还挺好,看来大家在JS优化的问题上越来越注重“与国际接轨”了。一起来看本文的下篇,也是干货满满。文章目录6.AvoidlargeobjectsWhattheeffshouldIdoaboutthis?7.Useeval8.Usestrings,carefullyWhattheeffs......
  • 期末所需分数.java
    原始问题描述期末考试满分100分,平时成绩满分40分。总评成绩由期末考成绩的60%和平时成绩组成。已知平时成绩,求期末考试至少需得多少分,以确保总评成绩不低于60分。原始版本参考代码importjava.util.Scanner;publicclassFishTank{publicstaticvoidmain(String[]ar......
  • Javaweb之SpringBootWeb案例之修改员工的修改回显的详细解析
     3.修改员工需求:修改员工信息编辑在进行修改员工信息的时候,我们首先先要根据员工的ID查询员工的信息用于页面回显展示,然后用户修改员工数据之后,点击保存按钮,就可以将修改的数据提交到服务端,保存到数据库。具体操作为:根据ID查询员工信息保存修改的员工信息3.1查询回显3.1.1接口......
  • java+vue计算机毕设大学生法律咨询系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,随着法治观念的深入人心和互联网技术的飞速发展,大学生群体对法律知识的需求日益增长。然而,面对复杂的法律条文和实际问题,大学生往往感到迷......
  • java+vue计算机毕设德云社票务系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着文化娱乐产业的蓬勃发展,相声艺术作为中国传统文化的瑰宝,在现代社会中焕发出新的生机。德云社,作为相声界的领军品牌,其演出活动频繁且备受观众喜爱......
  • java+vue计算机毕设丹徒高级中学校车预约【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着教育事业的快速发展和城市化进程的加速,丹徒高级中学作为地区内的重要教育机构,面临着学生数量增长与交通出行需求日益增长的双重挑战。传统的校车......
  • java计算机毕业设计漫语在线论坛设计与实现(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,网络社区已成为人们交流思想、分享信息、建立社交关系的重要平台。在线论坛作为网络社区的一种典型形式,凭借其开放性、互动......
  • java计算机毕业设计家庭智能理财管理(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着科技的飞速发展,智能化已成为现代生活的重要特征,尤其在金融管理领域,家庭智能理财管理的需求日益凸显。在快节奏的现代生活中,家庭财务管理变得复杂......