目次 | 前の項目 | 次の項目 Java Native Interface 仕様

JNI の型とデータ構造


第 3 章

この章では、JNI がどのように Java の型をネイティブ C の型にマッピングするかを解説します。

プリミティブ型

表 3-1 は、Java のプリミティブ型およびそれらのマシン依存のネイティブ型との対応について説明しています。

表 3-1 プリミティブ型とネイティブ型
Java のデータ型
ネイティブ型
説明
boolean
jboolean
unsigned 8 ビット
byte
jbyte
signed 8 ビット
char
jchar
unsigned 16 ビット
short
jshort
signed 16 ビット
int
jint
signed 32 ビット
long
jlong
signed 64 ビット
float
jfloat
32 ビット
double
jdouble
64 ビット
void
void
なし

次の定義は、利便性のため提供されています。

#define JNI_FALSE  0 
#define JNI_TRUE   1 

jsize 整数型は、基本的な添字およびサイズを記述するために使用されます。

typedef jint jsize; 

参照型

JNI には、各種の Java オブジェクトに対応する多くの参照型が含まれています。JNI 参照型は、図 3-1 に示すように、階層構造になっています。

階層の最上部は jobject です。jobject  のサブクラスは、jclass、jstring、jarray、および jthrowable です。jarray のサブクラスは、jobjectArray、jbooleanArray、jbyteArray、jcharArray、jshortArray、jintArray、jlongArray、jfloatArray、jdoubleArray です。

図 3-1 参照型の階層

C では、その他すべての JNI 参照型は、jobject と同じように定義されています。例を示します。

typedef jobject jclass; 

C++ では、JNI はダミークラスのセットを導入して、サブタイプ関係を強制します。例を示します。

class _jobject {}; 
class _jclass : public _jobject {}; 
... 
typedef _jobject *jobject; 
typedef _jclass *jclass; 

フィールドとメソッド ID

フィールドとメソッド ID は、次のように正規の C ポインタ型です。

struct _jfieldID;              /* opaque structure */ 
typedef struct _jfieldID *jfieldID;   /* field IDs */ 
 
struct _jmethodID;              /* opaque structure */ 
typedef struct _jmethodID *jmethodID; /* method IDs */ 

値の型

jvalue 共用体型は、引数配列で要素型として使用されます。これは次のように宣言されます。

typedef union jvalue { 
    jboolean z; 
    jbyte    b; 
    jchar    c; 
    jshort   s; 
    jint     i; 
    jlong    j; 
    jfloat   f; 
    jdouble  d; 
    jobject  l; 
} jvalue; 

型のシグニチャー

JNI は、Java VM の型のシグニチャー表現を使用します。表 3-2 は、これらの型のシグニチャーを示しています。

表 3-2 Java VM の型のシグニチャー
Type Signature
Java のデータ型
Z
boolean
B
byte
C
char
S
short
I
int
J
long
F
float
D
double
L fully-qualified-class ;
完全指定のクラス
[ type
type[]
( arg-types ) ret-type
メソッドの型

たとえば、次の Java メソッドには、

long f (int n, String s, int[] arr); 

次のような型のシグニチャーがあります。

(ILjava/lang/String;[I)J 

変更後の UTF-8 文字列

JNI は変更後の UTF-8 文字列を使用して各種の文字列型を表現します。変更後の UTF-8 文字列は Java VM によって使用されるものと同じです。変更後の UTF-8 文字列は、1 文字につき 1 バイトだけを使用して null 以外の ASCII 文字だけが含まれる文字シーケンスが表現できるようにコード化されていますが、Unicode 文字もすべて表現できます。

次のように、\u0001 ~ \u007F の範囲のすべての文字が 1 バイトで表現されます。

0

bits 6-0

バイトのうち 7 ビットのデータは、表現されている文字の値を示します。

null 文字 (「\u0000」) および「\u0080」「\u07FF」のすべての文字は、次のように x と y の一対のバイトで表現されます。

x:

1

1

0

bits 10-6
y:

1

0

bits 5-0

このバイトは、((x & 0x1f) << 6) + (y & 0x3f) の値で文字を表現します。

「\u0800」「\uFFFF」の文字は、次のように x、y および z の 3 バイトで表現されます。

x:

1

1

1

0

bits 15-12
y:

1

0

bits 11-6
z:

1

0

bits 5-0

((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f) という値の文字がバイトで表現されます。

U+FFFF より大きなコードポイントを持つ文字 (いわゆる「補助文字」) は、UTF-16 表現の2つの代理コード単位を別々にエンコードすることで表現されます。代理コード単位はそれぞれ 3 バイトで表現されます。つまり、補助文字は、uvwxyz の 6 バイトで表現されます。

u:

1

1

1

0

1

1

0

1
v:

1

0

1

0

(bits 20-16) - 1
w:

1

0

bits 15-10
x:

1

1

1

0

1

1

0

1
y:

1

0

1

1

bits 9-6
z:

1

0

bits 5-0

値が 0x10000+((v&0x0f)<<16)+((w&0x3f)<<10)+(y&0x0f)<<6)+(z&0x3f) の文字は 6 バイトで表現されます。

マルチバイト文字のバイトは、class ファイルにビッグエンディアン順 (高位バイトが先) に格納されています。

この形式と標準 UTF-8 形式とでは、2 つの相違点があります。第一は、null 文字 (char)0 が、1 バイト形式でなく 2 バイト形式でコード化されていることです。これは、変更後の UTF-8 文字列に null が組み込まれないことを意味します。第ニは、標準 UTF-8 の 1 バイト、2 バイト、および 3 バイト形式だけが使用されていることです。Java VM は、標準 UTF-8 の 4 バイト形式を認識せず、2 x 3 バイト形式を使用します。

標準 UTF-8 形式に関する詳細は、『The Unicode Standard, Version 4.0』の「3.9 Unicode Encoding Forms」を参照してください。

 


目次 | 前の項目 | 次の項目