Coins Java - Experiment08

プリミティブ配列にアクセスする

[Coins Java - Experiment]

目的

作業

Guide to GNU gcj - About CNIを読むと、Arraysの項目にGCJでの配列の構造が記されている。

class __JArray : public java::lang::Object
{
public:
  int length;
};

template<class T>
class JArray : public __JArray
{
  T data[0];
public:
  T& operator[](jint i) { return data[i]; }
};

java.lang.Objectを継承している点から、以下のような構造だと推測できる。

これにアクセスするようなプログラムを作る。

まずは配列を初期化し、クラスフィールドに納め、CNIからそれにアクセスするようにする。

$ emacs Start.java
--- Start.java
public class Start {

    public static int[] array;

    public static void main(String[] args) {
        array = new int[5];
        array[0] = 100;
        array[1] = 200;
        array[2] = 300;
        array[3] = 400;
        array[4] = 500;
        nativeMethod();
    }

    public static native void nativeMethod();
}
---
$ gcj -C Start.java
$ gcjh Start

実際にアクセスする。VTableの存在を確認するため、hashCode()を呼び出す。

$ emacs natStart.cc
--- natStart.cc
#include <stdio.h>

#include "Start.h"

extern "C" void arrayAccess(void *);

void Start::nativeMethod (){
  printf("CNI : array.hashCode() = %d\n", ::Start::array->hashCode());
  arrayAccess(::Start::array);
}

void arrayAccess(void *array) {
  printf("%08x : Pointer to VTable?\n", ((long *)array)[0]);
  printf("length = %d\n", ((long *)array)[1]);
  printf("array[0] = %d\n", ((long *)array)[2]);
  printf("array[1] = %d\n", ((long *)array)[3]);
  printf("array[2] = %d\n", ((long *)array)[4]);
  printf("array[3] = %d\n", ((long *)array)[5]);
  printf("array[4] = %d\n", ((long *)array)[6]);

  long *vtable = *(long **)array;
  void *hashcode = (void *)vtable[3];
  printf("VTABLE : array.hashCode() = %d\n", ((long (*)(void *))hashcode)(array));
}
---
$ gcc -c natStart.cc

コンパイル

$ gcj --main=Start *.class *.o

結果

以下のようになった。

$ ./a.out
CNI : array.hashCode() = 137139968
0097dbb8 : Pointer to VTable?
length = 5
array[0] = 100
array[1] = 200
array[2] = 300
array[3] = 400
array[4] = 500
VTABLE : array.hashCode() = 137139968

CNIから呼び出したhashCodeとVTABLEを直接叩いたhashCodeが返す値が同じになっていることが確認できる。

また、その他の要素についても予想通りの配置をしていた。

考察

この構造ならば配列がプリミティブかどうかを確認しないでもアクセスできそうな雰囲気である。

Copyright (C) 2002-2006 s.arakawa