Java安全基础——JNI安全基础

前言:Java语言是基于C语言实现的,Java底层的很多API都是通过JNI(Java Native Interface)来实现的。通过JNI接口C/C++Java可以互相调用(存在跨平台问题)。Java可以通过JNI调用来弥补语言自身的不足(代码安全性、内存操作等)。这个看似非常炫酷的特性其实自JDK1.1开始就有了,但是我们不得不去考虑JNI调用带来的一系列的安全问题!

1:使用java调用c或者c++的函数

(1)想要在java中调用c或者c++编写的函数,首先在想要被c或者c++编写的方法的前面加上native关键字,定义一个类似于接口的方法就行了

复制代码
public static native int add(int a, int b);

(2)使用动态代码块进行动态链接库的加载

后缀名:windows:.dll linux:.so .dll可以省略

路径:在同目录下不需要加路径,只需写库名就行了,在别的地方需要加上路径

复制代码
static {
    try {
        // 使用绝对路径加载DLL
        System.load("E:\\JavaProject\\untitled\\dll\\cmd.dll");
        System.out.println("DLL加载成功!");
    } catch (UnsatisfiedLinkError e) {
        System.err.println("无法加载DLL: " + e.getMessage());
        e.printStackTrace();
        System.exit(1);
    }
}

(3)生成类头文件

javac -h 路径 文件名(jdk10+)

javac -h E:\JavaProject\untitled\src\main\java\org\cmd cmd.java

执行上面所述的命令后即可看到org_example_cmd.h这个头文件

复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_example_cmd */

#ifndef _Included_org_example_cmd
#define _Included_org_example_cmd
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_example_cmd
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_org_example_cmd_add
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

(4)编写声明的函数

生成一个.cpp文件,并把org_example_cmd.h中的声明的函数复制到,c++或c中写

复制代码
#include"org_example_cmd.h"
#include <iostream>
JNIEXPORT jint JNICALL Java_org_example_cmd_add(JNIEnv *, jclass, jint a, jint b)
{
    std::cout << "a=" << a << std::endl;
    std::cout << "b=" << b << std::endl;
    return a+b;
}

(5)将c或者c++写的函数编写成动态链接库

g++ -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o cmd.dll cmd.cpp

执行完上面这行会生成一个cmd.dll

(6)利用类名调用方法即可,即可间接调用用c++的函数

复制代码
cmd.add(100,200);

2:Java数据类型,JNI数据类型,C++数据类型之间的关系

JNI类型其实就是C++ 用typedef重命名的类型,实际上java把类型转换成了C++类型了,基本类型直接使用,引用类型指向的对象的指针

  • JNIEnv 在C++中对应 JNIEnv_*(指向JNIEnv_结构体的指针)

  • jstring 在C++中对应 _jstring*(指向_jstring结构体的指针)

3:接受并返回JAVA String类型

1:编写方法

public static native String sub(String a);

2:生成头文件

javac -encoding UTF-8 -h ./ cmd.java

3:编写函数

JNIEXPORT jstring JNICALL Java_org_example_cmd_sub(JNIEnv *env, jclass, jstring str)

{

jboolean isCopy;

//复制字符串,并用指针p指向他

const char *p= env->GetStringUTFChars(str, &isCopy);

//打印字符串

std::cout << p << std::endl;

//释放资源

env->ReleaseStringUTFChars(str,p);

}

4:生成动态链接库

g++ -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o cmd.dll cmd.cpp

相关推荐
雾岛听蓝2 小时前
进程信号机制深度解析
linux·开发语言·经验分享·笔记
好家伙VCC4 小时前
**神经编码新视角:用Python实现生物启发的神经信号压缩与解码算法**在人工智能飞速发展的今天
java·人工智能·python·算法
一灯架构10 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
踏着七彩祥云的小丑10 小时前
pytest——Mark标记
开发语言·python·pytest
Dream of maid10 小时前
Python12(网络编程)
开发语言·网络·php
W230357657311 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
Y40900111 小时前
【多线程】线程安全(1)
java·开发语言·jvm
不爱吃炸鸡柳11 小时前
Python入门第一课:零基础认识Python + 环境搭建 + 基础语法精讲
开发语言·python
布局呆星11 小时前
SpringBoot 基础入门
java·spring boot·spring
minji...12 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法