我看JAVA 之 Object & JNI
注:基於jdk11
Object
Object類是java語言中所有類的父類。
public class Object {
//註冊本地函數,方可以從庫中的本機代碼調用JNI函數
private static native void registerNatives();
static {
registerNatives();
}
/**
* Constructs a new object.
*/
//HotSpotIntrinsicCandidate註解,說明本方法,jvm額外維護了一個利用了CPU指令的高效實現
@HotSpotIntrinsicCandidate
public Object() {}
//返回對象的運行時類型
/**
* Number c = 0;
* Class<? extends Number> clazz = c.getClass();
* System.out.println(clazz);
* 打印如下:
* class java.lang.Integer
* 關於泛型及泛型擦除概念,見後續泛型章節
*/
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
/**
* 返回對象的hash碼,hashCode方法支持hash表(比如java.util.HashMap)的特性,
* 不同的對象返回唯一的has碼,可以提高hash表數據結構的性能。
* hashCode有時候以對象內存地址的機制生成,有時候不是
* java.lang.System.identityHashCode 工具方法 返回默認hashCode()方法的值,null引用返回的hash碼爲0
*/
@HotSpotIntrinsicCandidate
public native int hashCode();
/**
* 標示其他對象與當前對象是否相等
* 自反性: 自己(非null)與自己比較永遠相當
* 對稱性: x vs y or y vs x 等價
* 可傳遞: x.equals(y) == true and y.equals(z), then x.equals(z)
* 一致性: 一旦x.equals(y) == true, then anytime x.equals(y) == true
* any not null value not equals null
* 如果覆蓋equals方法,一定要覆蓋hashCode方法
*/
public boolean equals(Object obj) {
return (this == obj);
}
/**
* clone返回會返回一個相同類型的新對象拷貝,如果要實現克隆,那麼當前類及其父類需要實現cloneable接口。
* 對於複雜類型,默認的clone方式僅實現”淺克隆”,如果要實現”深克隆”,需要覆蓋clone方法。
* 注:在軟件編程中,推薦使用工具類的方式做copy,而不是覆蓋clone的方式
*/
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
/**
* 默認返回 getClass().getName() + '@' + Integer.toHexString(hashCode())
* 具體類可以覆蓋Object的toString()方法
*/
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
/**
* 持有該對象鎖的線程通過調用notify喚醒等待此對象監視器的某一個線程,選擇是隨機的(具體由不同虛擬機實現)。一次只能有一個線程持有對象鎖。
* 獲取對象鎖定三種方式如下:
* 1,通過執行該對象的同步實例方法
* 2,通過執行該對象的同步代碼塊
* 3,通過執行類的同步靜態方法
* 見 /openjdk/hotspot/src/share/vm/prims/jvm.cpp line: 526~530
* 見 /openjdk/hotspot/src/share/vm/runtime/synchronizer.cpp line: 407~411
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @see java.lang.Object#notifyAll()
* @see java.lang.Object#wait()
*/
@HotSpotIntrinsicCandidate
public final native void notify();
/**
* 持有該對象鎖的線程通過調用notify喚醒等待此對象監視器的所有線程。噹噹前線程釋放對象監視器後,其他喚醒的線程會競爭對象監視器。
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @see java.lang.Object#notify()
* @see java.lang.Object#wait()
*/
@HotSpotIntrinsicCandidate
public final native void notifyAll();
/**
* 調用此方法會導致當前對象進入等待狀態,知道被其他線程喚醒(notify)或中斷(InterruptedException)。相當於wait(0L)
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait(long)
* @see #wait(long, int)
*/
public final void wait() throws InterruptedException {
wait(0L);
}
/**
*
* @param timeoutMillis the maximum time to wait, in milliseconds
* @throws IllegalArgumentException if {@code timeoutMillis} is negative
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait()
* @see #wait(long, int)
*/
public final native void wait(long timeoutMillis) throws InterruptedException;
/**
* 在併發編程章節重點講解
* @param timeoutMillis the maximum time to wait, in milliseconds
* @param nanos additional time, in nanoseconds, in the range range 0-999999 inclusive
* @throws IllegalArgumentException if {@code timeoutMillis} is negative,
* or if the value of {@code nanos} is out of range
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait()
* @see #wait(long)
*/
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeoutMillis++;
}
wait(timeoutMillis);
}
/**
* 通知垃圾回收器當前對應已經沒有引用了,具體回收還要看jvm內部實現。
* jdk9 標記位過時,在jvm原理章節重點講解
*
* @throws Throwable the {@code Exception} raised by this method
* @see java.lang.ref.WeakReference
* @see java.lang.ref.PhantomReference
* @jls 12.6 Finalization of Class Instances
*/
@Deprecated(since="9")
protected void finalize() throws Throwable { }
}
JNI(Java Native Interface)
java本地接口,意爲JAVA語言提供一套規範供操作系統底層實現,一般是C/C++語言,不同操作系統版本的jvm提供了相應的實現,以達到"Write Once Run Anywhere“
實現JNI大致步驟如下:
-
定義java程序
package chapter01; public class TestJNI { public native void hello();//所有native關鍵詞修飾的都是對本地的聲明 static { System.loadLibrary("hello");//載入本地庫 } public static void main(String[] args) { new TestJNI().hello(); } }
- 編譯javac chapter01/TestJNI.java,生成TestJNI.class
-
執行javac chapter01/TestJNI.java -h . ,生成JAVA本地接口chapter01_TestJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class chapter01_TestJNI */ #ifndef _Included_chapter01_TestJNI #define _Included_chapter01_TestJNI #ifdef __cplusplus extern "C" { #endif /* * Class: chapter01_TestJNI * Method: hello * Signature: ()V */ JNIEXPORT void JNICALL Java_chapter01_TestJNI_hello (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
注意:JNIEnv、 jobject等類型都是在jni.h頭文件中定義的,所以需要include jni.h
-
編寫步驟3的接口實現,創建TestJNIImpl.c
#include "jni.h" #include "chapter01_TestJNI.h" //#include otherheaders JNIEXPORT void JNICALL Java_chapter01_TestJNI_hello(JNIEnv *env, jobject obj) { printf("Helloworld!\n"); return; }
- 將本地方法編寫的文件生成動態鏈接庫
gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/include TestJNIImpl.c -o libhello.jnilib
注意:如果/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/include不存在jni_md.h的話,可以從 /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/include/darwin 拷貝過來 - 執行java程序 java -Djava.library.path=/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/include chapter01/TestJNI