本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。
1. VSCODE 插件
- Code Runner
- Extension Pack for Java
- Maven for Java
- Debugger for Java
- Test Runner for Java
- Project Manager for Java
- Language Support for Java™ by Red Hat
- Java Debugger
2. ubuntu20.04安装Java
默认的ubuntu20.04源仓库包含了两个openJDK软件包,Java Runtime Environment(JRE)和Java Development Kit(JDK)。JRE主要包含了Java虚拟机(JVM),类和允许你允许Java程序的二进制包。JDK包含JRE和用于构建Java应用的开发/调试工具和库文件.
Java11s java的一个长期支持版本,同时也是Ubuntu20.04的默认Java开发和运行环境。
-
安装
sudo apt-get update sudo apt-get -y install openjdk-11-jdk java --version
-
设置Java默认版本
java --version sudo update-alternatives --config java
已经安装的Java版本都会输出,输入想要设置为默认的序列化,按enter即可
-
Java_HOME环境变量
# 首先查看Java的安装位置 update-alternatives --config java # 打开/etc/environment文件 sudo vim /etc/environment # 将JAVA_HOME指定到OpenJDK11,在文件末尾添加 JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64" # 运行下述命令让shell生效 source /etc/environment # 验证JAVA_HOME环境变量 echo $JAVA_HOME
-
vscode Java_HOME环境变量配置
settings.json
"java.jdt.ls.java.home": "/usr/lib/jvm/java-11-openjdk-amd64",
3. java 编译
# 编译单个文件
javac test.java
javac test
# package
javac -d . *.java
java animals/MammalInt
javac -d ../ JNIDemo.java Java2Cplusplus.java BaseClass.java
javac test.java
java -Djava.library.path=./JNIDemo test
# JNI
javac -h . JNIDemo.java
javap -s -p Java2Cplusplus.class
# cpp
g++ -fPIC -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/ -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/linux/ -shared -o libcom_huhu_test_JNIDemo.so com_huhu_test_JNIDemo.cpp
4. JNI
4.1. JAVA调用C++
import com.huhu.test.*;
/* 文件名 : MammalInt.java */
public class test
{
public static void main(String[] args)
{
//加载C文件
System.loadLibrary("com_huhu_test_JNIDemo");
JNIDemo jniDemo = new JNIDemo();
jniDemo.testHello();
int[] data = {1, 2, 3};
float[] f = jniDemo.execute(data, 1, 2, 3);
System.out.println(f[0]);
System.out.println(f[1]);
System.out.println(f[2]);
}
}
4.2. 生成 头文件 com_huhu_test_JNIDemo
javac -h . JNIDemo.java
JNIDemo.java :
package com.huhu.test;
public class JNIDemo
{
//定义一个方法,该方法在C中实现
public native void testHello();
public native float[] execute(int[] data, int width, int height, float ep);
}
com_huhu_test_JNIDemo.h :
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_huhu_test_JNIDemo */
#ifndef _Included_com_huhu_test_JNIDemo
#define _Included_com_huhu_test_JNIDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_huhu_test_JNIDemo
* Method: testHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_huhu_test_JNIDemo_testHello
(JNIEnv *, jobject);
/*
* Class: com_huhu_test_JNIDemo
* Method: execute
* Signature: ([IIIF)[F
*/
JNIEXPORT jfloatArray JNICALL Java_com_huhu_test_JNIDemo_execute
(JNIEnv *, jobject, jintArray, jint, jint, jfloat);
#ifdef __cplusplus
}
#endif
#endif
4.3. 实现 com_huhu_test_JNIDemo
com_huhu_test_JNIDemo.cpp:
// g++ -fPIC -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/ -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/linux/ -shared -o libTestJni.so
// TestJni.cpp
#include "com_huhu_test_JNIDemo.h"
#include <jni.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define JNI_JAVA2C_PATH "com/huhu/test/Java2Cplusplus"
#define JNI_BASE_CLASS_PATH "com/huhu/test/BaseClass"
JNIEXPORT void JNICALL Java_com_huhu_test_JNIDemo_testHello(JNIEnv *env, jobject thiz)
{
std::cout << "this is Java_com_huhu_test_JNIDemo_testHello C++ print" << std::endl;
}
JNIEXPORT jfloatArray JNICALL Java_com_huhu_test_JNIDemo_execute(JNIEnv *env, jobject thiz, jintArray data, jint width, jint height, jfloat ep)
{
std::cout << "this is Java_com_huhu_test_JNIDemo_execute C++ print" << std::endl;
unsigned char *data_src = (unsigned char *)env->GetIntArrayElements(data, NULL);
std::cout << "data_src " << data_src[0] << " " << data_src[1] << " " << data_src[2] << " " << std::endl;
std::cout << "width height ep " << width << " " << height << " " << ep << " " << std::endl;
std::vector<float> result{0.1, 0.2, 0.3};
jfloatArray resultArray = env->NewFloatArray(result.size());
env->SetFloatArrayRegion(resultArray, 0, result.size(), &result[0]);
/* ------------------ */
//步骤1:
jclass clazz = env->FindClass(JNI_JAVA2C_PATH);
//步骤2:<init>是java的构造函数名,这个有点特殊。在我的一篇文章jetpack中的问题中碰见过它。
//构造函数没输入输出参数,所以这里的signature填写为()V
jmethodID method_init_id = env->GetMethodID(clazz, "<init>", "()V");
jmethodID method_set_id = env->GetMethodID(clazz, "setNum", "(I)V");
jmethodID method_get_id = env->GetMethodID(clazz, "getNum", "()I");
jclass base = env->FindClass(JNI_BASE_CLASS_PATH);
jmethodID method_base_init_id = env->GetMethodID(base, "<init>", "()V");
jobject objbase = env->NewObject(base, method_base_init_id);
jmethodID method_get_jobject_id = env->GetMethodID(clazz, "getNum", "(Lcom/huhu/test/BaseClass;)I");
//步骤3:
//创建了 Java2Cplusplus 对象
jobject obj = env->NewObject(clazz, method_init_id);
//步骤4:调用相应的方法
env->CallVoidMethod(obj, method_set_id, 21); // set函数没返回值
int year = env->CallIntMethod(obj, method_get_id); // getYear有返回值
int year2 = env->CallIntMethod(obj, method_get_jobject_id,objbase); // getYear有返回值
std::cout << "year " << year << std::endl;
std::cout << "year2 " << year2 << std::endl;
/* ------------------ */
return resultArray;
}
4.4. 编译 com_huhu_test_JNIDemo.cpp
g++ -fPIC -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/ -I /usr/lib/jvm/java-1.11.0-openjdk-amd64/include/linux/ -shared -o libcom_huhu_test_JNIDemo.so com_huhu_test_JNIDemo.cpp
4.5. 编译运行 java
javac -d ../ JNIDemo.java Java2Cplusplus.java BaseClass.java
cd ../
javac test.java
java -Djava.library.path=./JNIDemo test
4.6. JNI GetFieldID和GetMethodID 所需签名参数
调用JNI的GetMethodID函数获取一个jmethodID时,需要传入一个方法名称和方法签名,方法名称就是在Java中定义的方法名,方法签名的格式为:(形参参数类型列表)返回值。
1.基本类型签名
Java | Native | Signature |
---|---|---|
byte | jbyte | B |
char | jchar | C |
double | jdouble | D |
float | jfloat | F |
int | jint | I |
short | jshort | S |
long | jlong | J |
boolean | jboolean | Z |
void | void | V |
2.引用数据类型的转换.
Java | Native | Signature |
---|---|---|
所有对象 | jobject | L+classname +; |
Class | jclass | Ljava/lang/Class; |
String | jstring | Ljava/lang/String; |
Throwable | jthrowable | Ljava/lang/Throwable; |
Object[] | jobjectArray | [L+classname +; |
byte[] | jbyteArray | [B |
char[] | jcharArray | [C |
double[] | jdoubleArray | [D |
float[] | jfloatArray | [F |
int[] | jintArray | [I |
short[] | jshortArrsy | [S |
long[] | jlongArray | [J |
boolean[] | jbooleanArray | [Z |
获取签名方式:
- 自己拼写
方法:int (int param);
签名:(I)I
- 命令行生成
1、使用javac,生成对应java文件的class文件;
2、使用 javap -s -p 命令获取对应签名信息,如图:
Compiled from "Java2Cplusplus.java"
public class com.huhu.test.Java2Cplusplus {
private int num;
descriptor: I
public com.huhu.test.Java2Cplusplus();
descriptor: ()V
public void setNum(int);
descriptor: (I)V
public int getNum();
descriptor: ()I
public int getBaseClassNum(com.huhu.test.BaseClass);
descriptor: (Lcom/huhu/test/BaseClass;)I
}