目次 | 前の項目 | 次の項目 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 型のシグニチャー
型のシグニチャー
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

ビット 6-0

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

null 文字 (\u000) および \u0080\u07FF の範囲のすべての文字は、次のように x と y のバイトの組み合わせで表現されます。

x:

1

1

0

ビット 10-6
y:

1

0

ビット 5-0

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

\u0800\uFFFF の文字は、x、y、z の 3 バイトで表現されます。

x:

1

1

1

0

ビット 15-12
y:

1

0

ビット 11-6
z:

1

0

ビット 5-0

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

コードポイントが U+FFFF より上の文字 (いわゆる「補助文字」) は、対応する UTF-16 表現の 2 つの代理コード単位を別々に符号化することで表現されます。代理コード単位は、それぞれ 3 バイトで表現されます。すなわち、補助文字は uvwxy、および z の 6 バイトで表現されます。

u:

1

1

1

0

1

1

0

1
v:

1

0

1

0

(ビット 20-16) - 1
w:

1

0

ビット 15-10
x:

1

1

1

0

1

1

0

1
y:

1

0

1

1

ビット 9-6
z:

1

0

ビット 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 を組み込むことがないことを意味します。第ニは、1 バイト、2 バイト、および 3 バイト形式の標準 UTF-8 だけが使用されていることです。Java VM は 4 バイト形式の標準 UTF-8 を認識しません。Java VM は独自の 2X3 バイト形式を使用します。

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

 


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