gcj/15


gcj

15. コンスタントプール

実は今のままでは文字列の処理に重大な支障があり実用に耐えない。

前提情報

要旨

問題点

対策

確認

A.java

public class A {
	public static void main(String[] args) {
		System.out.println("abc");
	}
}

A.s

java.lang.String

gcj/cni.h

データ構造がある程度規定されている。

extern inline jchar *
_Jv_GetStringChars (jstring str)
{
  return (jchar*)((char*) str->data + str->boffset);
}

java/lang/String.java

package java.lang;

public class String {
	public String() {}
	public String toString() { return this; }
	public final int length() { return count; }
	/*private*/ public Object data = null;
	/*private*/ public int boffset = 0, count = 0;
}

PrintStream.cpp(修正)

今までは_Jv_Utf8Constが来ることを想定していたため修正。

void java::io::PrintStream::print(::java::lang::String* s) {
	int len = s->length();
	jchar* ch = _Jv_GetStringChars(s);
	for (int i = 0; i < len; i++, ch++) {
		printf("%c", (*ch < 128) ? (char)*ch : '?');
	}
}

javalang.cpp(追加)

とりあえず変換の不要なLatin1を実装。

extern "C" jstring _Jv_NewStringLatin1(const char* bytes, jsize len) {
	jstring s = new ::java::lang::String();
	s->data = _Jv_NewPrimArray(_Jv_charClass, len);
	s->boffset = sizeof(::java::lang::Object) + sizeof(jsize);
	s->count = len;
	jchar* ch = _Jv_GetStringChars(s);
	for (int i = 0; i < len; i++) ch[i] = (jchar)bytes[i];
	return s;
}

main.cpp

テスト

#include <java/lang/System.h>
#include <java/io/PrintStream.h>
#include <gcj/cni.h>
#include <sms_gc.h>
#include "A.h"

int main() {
	SMS_GC_INIT();
	JvCreateJavaVM(NULL);
	::java::lang::System::out->println(JvNewStringLatin1("Hello, World!"));
	return 0;
}

実行結果

$ ./test.exe
Hello, World!

コンスタントプールの書き換え

コンスタントプールを調べて、tagが8(=JV_CONSTANT_String)であれば、Stringインスタンスを生成してdataを書き換える。

java/lang/Class.h

 inline friend void
 _Jv_InitClass (jclass klass)
 {
   if (__builtin_expect (klass->state == JV_STATE_DONE, true))
     return;
   klass->initializeClass ();
 }

realize.cpp

仕方ないので最適化を掛けないソースを用意してダミー関数から呼ぶことで定義する。

#include <java/lang/Class.h>

static void dummy() {
	_Jv_InitClass(0);
}

java/lang/Class.java

package java.lang;

public class Class {
	private final native void initializeClass();
}

Class.cpp

gcjh -stubsで生成したものを手動で編集。

#include <java/lang/Class.h>
#include <gcj/cni.h>
#include <sms_gc.h>

void
java::lang::Class::initializeClass ()
{
	for (int i = 1; i < constants.size; i++) {
		if (constants.tags[i] == 8) {
			void** p = (void**)constants.data + i;
			sms_gc_register(p);
			*p = JvNewStringLatin1(((_Jv_Utf8Const*)*p)->data);
		}
	}
	state = JV_STATE_DONE;
}

Object.cpp(修正)

toString()が_Jv_Utf8Const前提だったので修正。

::java::lang::String *
java::lang::Object::toString ()
{
	return JvNewStringLatin1(
		((_Jv_Utf8Const*)*((void**)((jobject)getClass() + 1) + 1))->data);
}

main.cpp

#include <gcj/cni.h>
#include <sms_gc.h>
#include "A.h"

int main() {
	SMS_GC_INIT();
	JvCreateJavaVM(NULL);
	::A::main(NULL);
	return 0;
}

A.java

import java.lang.*;
import java.io.*;

public class A {
	public static void main(String[] args) {
		System.out.println(new Object());
		System.out.println("abc");
		System.out.println("abc".length());
	}
}

実行結果

$ ./test.exe
java.lang.Object
abc
3

ここまでの作業結果: file15.zip

Monaでの実行例

gcj.gif

gcj.tar.gz

MENU

now: 3

リンク


最新の20件
2018-05-03 2017-09-29 2017-04-25 2017-01-10 2016-12-11 2016-10-04 2016-08-14 2016-06-05 2016-05-29 2016-04-15 2015-12-28 2013-02-25 2013-02-21 2013-02-20 2013-02-12 2013-02-11 2013-02-10
最新の20件
2010-02-01 2010-01-31 2010-01-30 2010-01-29 2010-01-16

Counter: 3483, today: 1, yesterday: 1

添付ファイル: filegcj.gif 489件 [詳細]

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS

Last-modified: 2008-03-28 (金) 15:48:00 (3793d);  Modified by mona
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji
Powered by PHP 5.2.17
HTML convert time to 0.035 sec.