本文目錄一覽:
- 1、關於Android開發中Java對於.so庫的調用
- 2、java調用so方法如何返回對象
- 3、java 調用so文件
- 4、Java 在eclipse中,web項目如何加載.so文件的詳細步驟
- 5、如何把JAVA工程 編譯成.SO文件
關於Android開發中Java對於.so庫的調用
android掉用c的so包就是通過jni
,
應該給你的jar包就是用來調用so包的
。不會讓你直接掉so包的放心。so包一般都是為了保證核心代碼不被反編譯
,另外就是效率高才會用,或者就是開發遊戲
。
他們說夠用應該是jar包已經和so包的jni調用接口都調好了
,
你用jar包就行了
java調用so方法如何返回對象
雖然Java 嚴格按照值傳遞,但是精確的效果在傳遞基本類型還是引用類型之間是不同的。
當我們將一個原始類型傳遞給一個方法時,它將按值傳遞。但是當我們將一個對象傳遞給一個方法時,情況會發生巨大的變化,因為對象是通過有效調用的方式傳遞的。Java做這個有趣的事情,這是一種混合傳遞值和傳遞引用。基本上,函數不能更改參數,但函數可以通過調用其中的某些方法來讓參數自行更改。
在創建類類型的變量時,我們只創建一個對象的引用。因此,當我們將此引用傳遞給方法時,接收它的參數將引用與參數引用的對象相同的對象。
這實際上意味着對象的行為就好像通過使用引用調用來傳遞給方法一樣。
方法內部對象的改變確實反映在用作參數的對象中。
在Java中,我們可以將對象傳遞給方法。例如,請考慮以下程序:
// Java program to demonstrate objects
// passing to methods.
class ObjectPassDemo
{
int a, b;
ObjectPassDemo(int i, int j)
{
a = i;
b = j;
}
// return true if o is equal to the invoking
// object notice an object is passed as an
// argument to method
boolean equalTo(ObjectPassDemo o)
{
return (o.a == a o.b == b);
}
}
// Driver class
public class Test
{
public static void main(String args[])
{
ObjectPassDemo ob1 = new ObjectPassDemo(100, 22);
ObjectPassDemo ob2 = new ObjectPassDemo(100, 22);
ObjectPassDemo ob3 = new ObjectPassDemo(-1, -1);
System.out.println(“ob1 == ob2: ” + ob1.equalTo(ob2));
System.out.println(“ob1 == ob3: ” + ob1.equalTo(ob3));
}
}
輸出:
ob1 == ob2:true
ob1 == ob3:false
創建了三個對象’ob1’,’ob2’和’ob3’:
ObjectPassDemo ob1 = new ObjectPassDemo(100,22);
ObjectPassDemo ob2 = new ObjectPassDemo(100,22);
ObjectPassDemo ob3 = new ObjectPassDemo(-1,-1);
在方法方面,聲明了一個名為a的Foo類型的引用,並且它的初始值為null。
boolean equalTo(ObjectPassDemo o);
當我們調用方法equalTo時,引用’o’將被分配給作為參數傳遞的對象,即’o’將引用’ob2’作為以下語句執行。
System.out.println(「ob1 == ob2:」+ ob1.equalTo(ob2));
現在我們可以看到,’ob1’上調用了equalTo方法,’o’指的是’ob2’。由於’a’和’b’的值對於兩個引用都是相同的,所以如果(條件)為真,那麼將返回布爾值true。
if(oa == a ob == b)
執行以下語句時,’o’將重新分配給’ob3’。
System.out.println(「ob1 == ob3:」+ ob1.equalTo(ob3));
現在我們可以看到,’ob1’上調用了equalTo方法,’o’指的是’ob3’。由於’a’和’b’的值對於兩個引用都不相同,所以如果(條件)為假,那麼else塊將執行並且將返回false。
定義一個將其類的對象作為參數的構造函數
對象參數最常見的用途之一是構造函數。通常,在實踐中,需要構建一個新對象,以便它最初與某個現有對象相同。為此,我們可以使用Object.clone()方法或定義一個將其類的對象作為參數的構造函數。下面的例子說明了第二個選項:
// Java program to demonstrate one object to
// initialize another
class Box
{
double width, height, depth;
// Notice this constructor. It takes an
// object of type Box. This constructor use
// one object to initialize another
Box(Box ob)
{
width = ob.width;
height = ob.height;
depth = ob.depth;
}
// constructor used when all dimensions
// specified
Box(double w, double h, double d)
{
width = w;
height = h;
depth = d;
}
// compute and return volume
double volume()
{
return width * height * depth;
}
}
// driver class
public class Test
{
public static void main(String args[])
{
// creating a box with all dimensions specified
Box mybox = new Box(10, 20, 15);
// creating a copy of mybox
Box myclone = new Box(mybox);
double vol;
// get volume of mybox
vol = mybox.volume();
System.out.println(“Volume of mybox is ” + vol);
// get volume of myclone
vol = myclone.volume();
System.out.println(“Volume of myclone is ” + vol);
}
}
輸出:
Volume of mybox is 3000.0
Volume of myclone is 3000.0
返回對象
在java中,一個方法可以返回任何類型的數據,包括對象。例如,在以下程序中,incrByTen()方法返回一個對象,其中(整數變量)的值比調用對象中的值大10。
// Java program to demonstrate returning
// of objects
class ObjectReturnDemo
{
int a;
ObjectReturnDemo(int i)
{
a = i;
}
// This method returns an object
ObjectReturnDemo incrByTen()
{
ObjectReturnDemo temp =
new ObjectReturnDemo(a+10);
return temp;
}
}
// Driver class
public class Test
{
public static void main(String args[])
{
ObjectReturnDemo ob1 = new ObjectReturnDemo(2);
ObjectReturnDemo ob2;
ob2 = ob1.incrByTen();
System.out.println(“ob1.a: ” + ob1.a);
System.out.println(“ob2.a: ” + ob2.a);
}
}
輸出:
ob1.a:2
ob2.a:12
java 調用so文件
用JNI實現
實例:
創建HelloWorld.java
class HelloWorld
{
private native void print();
public staticvoid main(String[] args)
{
new HelloWorld().print();
}
static
{
System.loadLibrary(“HelloWorld”);
}
}
注意print方法的聲明,關鍵字native表明該方法是一個原生代碼實現的。另外注意static代碼段的System.loadLibrary調用,這段代碼表示在程序加載的時候,自動加載libHelloWorld.so庫。
編譯HelloWorld.java
在命令行中運行如下命令:
javac HelloWorld.java
在當前文件夾編譯生成HelloWorld.class。
生成HelloWorld.h
在命令行中運行如下命令:
javah -jni HelloWorld
在當前文件夾中會生成HelloWorld.h。打開HelloWorld.h將會發現如下代碼:
/* DO NOT EDIT THIS FILE – it is machine generated */
#include jni.h
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
該文件中包含了一個函數Java_HelloWorld_print的聲明。這裏面包含兩個參數,非常重要,後面講實現的時候會講到。
實現HelloWorld.c
創建HelloWorld.c文件輸入如下的代碼:
#include jni.h
#include stdio.h
#include “HelloWorld.h”
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf(“Hello World!\n”);
}
注意必須要包含jni.h頭文件,該文件中定義了JNI用到的各種類型,宏定義等。
另外需要注意Java_HelloWorld_print的兩個參數,本例比較簡單,不需要用到這兩個參數。但是這兩個參數在JNI中非常重要。
env代表java虛擬機環境,Java傳過來的參數和c有很大的不同,需要調用JVM提供的接口來轉換成C類型的,就是通過調用env方法來完成轉換的。
obj代表調用的對象,相當於c++的this。當c函數需要改變調用對象成員變量時,可以通過操作這個對象來完成。
編譯生成libHelloWorld.so
在Linux下執行如下命令來完成編譯工作:
cc -I/usr/lib/jvm/java-6-sun/include/linux/
-I/usr/lib/jvm/java-6-sun/include/
-fPIC -shared -o libHelloWorld.so HelloWorld.c
在當前目錄生成libHelloWorld.so。注意一定需要包含Java的include目錄(請根據自己系統環境設定),因為Helloworld.c中包含了jni.h。
另外一個值得注意的是在HelloWorld.java中我們LoadLibrary方法加載的是
「HelloWorld」,可我們生成的Library卻是libHelloWorld。這是Linux的鏈接規定的,一個庫的必須要是:lib+庫
名+.so。鏈接的時候只需要提供庫名就可以了。
運行Java程序HelloWorld
大功告成最後一步,驗證前面的成果的時刻到了:
java HelloWorld
如果你這步發生問題,如果這步你收到java.lang.UnsatisfiedLinkError異常,可以通過如下方式指明共享庫的路徑:
java -Djava.library.path=’.’ HelloWorld
當然還有其他的方式可以指明路徑請參考《在Linux平台下使用JNI》。
我們可以看到久違的「Hello world!」輸出了。
Java 在eclipse中,web項目如何加載.so文件的詳細步驟
引入jna.jar包。 然後寫一個接口類繼承Library來和.so(linux平台)或.dll(windows平台)文件交互。接口中對應的方法為so中的方法,大小寫都需要完全一致,同時參數類型也需要注意,jna和so中的參數類型的對應轉換。
以下是代碼是大概例子,你可以看一下,是有參數的對應格式的。其中,Native.loadLibrary為加載鏈接庫文件。
public interface LibVlc extends Library {
Info INFO = Info.getInstance();
LibVlc INSTANCE = (LibVlc)Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
LibVlc SYNC_INSTANCE = (LibVlc)Native.synchronizedLibrary(INSTANCE);
String libvlc_errmsg();
void libvlc_clearerr();
libvlc_instance_t libvlc_new(int argc, String[] argv);
}
如何把JAVA工程 編譯成.SO文件
1,寫一個java文件,聲明一個native 方法,例如public native void test(); 2,把它編譯成class文件 3,使用javah 這個class來生成cpp的頭文件 4,實現頭文件裏面那些函數 4,用ndk編譯生成動態庫 其中1,想生成幾個就寫幾個native方法。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/308591.html