JNIEnv and JavaVM method implementations

This commit is contained in:
Joel Dice 2007-09-10 17:33:58 -06:00
parent a9f9755221
commit e5987f2a22
7 changed files with 326 additions and 72 deletions

View File

@ -252,6 +252,18 @@ const unsigned ACC_STRICT = 1 << 11;
const int JNI_COMMIT = 1; const int JNI_COMMIT = 1;
const int JNI_ABORT = 2; const int JNI_ABORT = 2;
const int JNI_OK = 0;
const int JNI_ERR = -1;
const int JNI_EDETACHED = -2;
const int JNI_EVERSION = -3;
const int JNI_ENOMEM = -4;
const int JNI_EEXIST = -5;
const int JNI_EINVAL = -6;
const int JNI_VERSION_1_1 = 0x00010001;
const int JNI_VERSION_1_2 = 0x00010002;
const int JNI_VERSION_1_4 = 0x00010004;
} // namespace vm } // namespace vm
#endif//CONSTANTS_H #endif//CONSTANTS_H

View File

@ -9,6 +9,45 @@ namespace {
const uintptr_t InterfaceMethodID const uintptr_t InterfaceMethodID
= (static_cast<uintptr_t>(1) << (BitsPerWord - 1)); = (static_cast<uintptr_t>(1) << (BitsPerWord - 1));
jint JNICALL
AttachCurrentThread(Machine* m, Thread** t, void*)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t == 0) {
*t = new (m->system->allocate(sizeof(Thread))) Thread(m, 0, m->rootThread);
m->localThread->set(*t);
}
return 0;
}
jint JNICALL
DetachCurrentThread(Machine* m)
{
Thread* t = static_cast<Thread*>(m->localThread->get());
if (t) {
t->exit();
return 0;
} else {
return -1;
}
}
jint JNICALL
GetEnv(Machine* m, Thread** t, jint version)
{
*t = static_cast<Thread*>(m->localThread->get());
if (*t) {
if (version <= JNI_VERSION_1_4) {
return JNI_OK;
} else {
return JNI_EVERSION;
}
} else {
return JNI_EDETACHED;
}
}
jsize JNICALL jsize JNICALL
GetStringUTFLength(Thread* t, jstring s) GetStringUTFLength(Thread* t, jstring s)
{ {
@ -981,6 +1020,70 @@ ExceptionClear(Thread* t)
t->exception = 0; t->exception = 0;
} }
jbooleanArray JNICALL
NewBooleanArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeBooleanArray(t, length, true));
}
jbyteArray JNICALL
NewByteArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeByteArray(t, length, true));
}
jcharArray JNICALL
NewCharArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeCharArray(t, length, true));
}
jshortArray JNICALL
NewShortArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeShortArray(t, length, true));
}
jintArray JNICALL
NewIntArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeIntArray(t, length, true));
}
jlongArray JNICALL
NewLongArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeLongArray(t, length, true));
}
jfloatArray JNICALL
NewFloatArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeFloatArray(t, length, true));
}
jdoubleArray JNICALL
NewDoubleArray(Thread* t, jsize length)
{
ENTER(t, Thread::ActiveState);
return pushReference(t, makeDoubleArray(t, length, true));
}
jboolean* JNICALL jboolean* JNICALL
GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy) GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
{ {
@ -1367,9 +1470,10 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
} }
jint JNICALL jint JNICALL
GetJavaVM(Thread* t, JavaVM** vm) GetJavaVM(Thread* t, Machine** m)
{ {
#warning todo *m = t->vm;
return 0;
} }
jboolean JNICALL jboolean JNICALL
@ -1377,7 +1481,7 @@ IsSameObject(Thread* t, jobject a, jobject b)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return a == b; return *a == *b;
} }
} // namespace } // namespace
@ -1385,60 +1489,149 @@ IsSameObject(Thread* t, jobject a, jobject b)
namespace vm { namespace vm {
void void
populateJNITable(JNIEnvVTable* table) populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
{ {
memset(table, 0, sizeof(JNIEnvVTable)); memset(vmTable, 0, sizeof(JavaVMVTable));
table->GetStringUTFLength = ::GetStringUTFLength; vmTable->AttachCurrentThread = AttachCurrentThread;
table->GetStringUTFChars = ::GetStringUTFChars; vmTable->DetachCurrentThread = DetachCurrentThread;
table->ReleaseStringUTFChars = ::ReleaseStringUTFChars; vmTable->GetEnv = GetEnv;
table->NewStringUTF = ::NewStringUTF;
table->GetByteArrayRegion = ::GetByteArrayRegion; memset(envTable, 0, sizeof(JNIEnvVTable));
table->SetByteArrayRegion = ::SetByteArrayRegion;
table->FindClass = ::FindClass; envTable->GetStringUTFLength = ::GetStringUTFLength;
table->ThrowNew = ::ThrowNew; envTable->GetStringUTFChars = ::GetStringUTFChars;
table->ExceptionCheck = ::ExceptionCheck; envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
table->DeleteLocalRef = ::DeleteLocalRef; envTable->NewStringUTF = ::NewStringUTF;
table->GetObjectClass = ::GetObjectClass; envTable->GetByteArrayRegion = ::GetByteArrayRegion;
table->IsInstanceOf = ::IsInstanceOf; envTable->SetByteArrayRegion = ::SetByteArrayRegion;
table->GetFieldID = ::GetFieldID; envTable->FindClass = ::FindClass;
table->GetStaticFieldID = ::GetStaticFieldID; envTable->ThrowNew = ::ThrowNew;
table->GetObjectField = ::GetObjectField; envTable->ExceptionCheck = ::ExceptionCheck;
table->GetBooleanField = ::GetBooleanField; envTable->DeleteLocalRef = ::DeleteLocalRef;
table->GetByteField = ::GetByteField; envTable->GetObjectClass = ::GetObjectClass;
table->GetCharField = ::GetCharField; envTable->IsInstanceOf = ::IsInstanceOf;
table->GetShortField = ::GetShortField; envTable->GetFieldID = ::GetFieldID;
table->GetIntField = ::GetIntField; envTable->GetMethodID = ::GetMethodID;
table->GetLongField = ::GetLongField; envTable->GetStaticMethodID = ::GetStaticMethodID;
table->GetFloatField = ::GetFloatField; envTable->CallObjectMethodV = ::CallObjectMethodV;
table->GetDoubleField = ::GetDoubleField; envTable->CallObjectMethod = ::CallObjectMethod;
table->SetObjectField = ::SetObjectField; envTable->CallBooleanMethodV = ::CallBooleanMethodV;
table->SetBooleanField = ::SetBooleanField; envTable->CallBooleanMethod = ::CallBooleanMethod;
table->SetByteField = ::SetByteField; envTable->CallByteMethodV = ::CallByteMethodV;
table->SetCharField = ::SetCharField; envTable->CallByteMethod = ::CallByteMethod;
table->SetShortField = ::SetShortField; envTable->CallCharMethodV = ::CallCharMethodV;
table->SetIntField = ::SetIntField; envTable->CallCharMethod = ::CallCharMethod;
table->SetLongField = ::SetLongField; envTable->CallShortMethodV = ::CallShortMethodV;
table->SetFloatField = ::SetFloatField; envTable->CallShortMethod = ::CallShortMethod;
table->SetDoubleField = ::SetDoubleField; envTable->CallIntMethodV = ::CallIntMethodV;
table->GetStaticObjectField = ::GetStaticObjectField; envTable->CallIntMethod = ::CallIntMethod;
table->GetStaticBooleanField = ::GetStaticBooleanField; envTable->CallLongMethodV = ::CallLongMethodV;
table->GetStaticByteField = ::GetStaticByteField; envTable->CallLongMethod = ::CallLongMethod;
table->GetStaticCharField = ::GetStaticCharField; envTable->CallFloatMethodV = ::CallFloatMethodV;
table->GetStaticShortField = ::GetStaticShortField; envTable->CallFloatMethod = ::CallFloatMethod;
table->GetStaticIntField = ::GetStaticIntField; envTable->CallDoubleMethodV = ::CallDoubleMethodV;
table->GetStaticLongField = ::GetStaticLongField; envTable->CallDoubleMethod = ::CallDoubleMethod;
table->GetStaticFloatField = ::GetStaticFloatField; envTable->CallVoidMethodV = ::CallVoidMethodV;
table->GetStaticDoubleField = ::GetStaticDoubleField; envTable->CallVoidMethod = ::CallVoidMethod;
table->SetStaticObjectField = ::SetStaticObjectField; envTable->CallStaticObjectMethodV = ::CallStaticObjectMethodV;
table->SetStaticBooleanField = ::SetStaticBooleanField; envTable->CallStaticObjectMethod = ::CallStaticObjectMethod;
table->SetStaticByteField = ::SetStaticByteField; envTable->CallStaticBooleanMethodV = ::CallStaticBooleanMethodV;
table->SetStaticCharField = ::SetStaticCharField; envTable->CallStaticBooleanMethod = ::CallStaticBooleanMethod;
table->SetStaticShortField = ::SetStaticShortField; envTable->CallStaticByteMethodV = ::CallStaticByteMethodV;
table->SetStaticIntField = ::SetStaticIntField; envTable->CallStaticByteMethod = ::CallStaticByteMethod;
table->SetStaticLongField = ::SetStaticLongField; envTable->CallStaticCharMethodV = ::CallStaticCharMethodV;
table->SetStaticFloatField = ::SetStaticFloatField; envTable->CallStaticCharMethod = ::CallStaticCharMethod;
table->SetStaticDoubleField = ::SetStaticDoubleField; envTable->CallStaticShortMethodV = ::CallStaticShortMethodV;
envTable->CallStaticShortMethod = ::CallStaticShortMethod;
envTable->CallStaticIntMethodV = ::CallStaticIntMethodV;
envTable->CallStaticIntMethod = ::CallStaticIntMethod;
envTable->CallStaticLongMethodV = ::CallStaticLongMethodV;
envTable->CallStaticLongMethod = ::CallStaticLongMethod;
envTable->CallStaticFloatMethodV = ::CallStaticFloatMethodV;
envTable->CallStaticFloatMethod = ::CallStaticFloatMethod;
envTable->CallStaticDoubleMethodV = ::CallStaticDoubleMethodV;
envTable->CallStaticDoubleMethod = ::CallStaticDoubleMethod;
envTable->CallStaticVoidMethodV = ::CallStaticVoidMethodV;
envTable->CallStaticVoidMethod = ::CallStaticVoidMethod;
envTable->GetStaticFieldID = ::GetStaticFieldID;
envTable->GetObjectField = ::GetObjectField;
envTable->GetBooleanField = ::GetBooleanField;
envTable->GetByteField = ::GetByteField;
envTable->GetCharField = ::GetCharField;
envTable->GetShortField = ::GetShortField;
envTable->GetIntField = ::GetIntField;
envTable->GetLongField = ::GetLongField;
envTable->GetFloatField = ::GetFloatField;
envTable->GetDoubleField = ::GetDoubleField;
envTable->SetObjectField = ::SetObjectField;
envTable->SetBooleanField = ::SetBooleanField;
envTable->SetByteField = ::SetByteField;
envTable->SetCharField = ::SetCharField;
envTable->SetShortField = ::SetShortField;
envTable->SetIntField = ::SetIntField;
envTable->SetLongField = ::SetLongField;
envTable->SetFloatField = ::SetFloatField;
envTable->SetDoubleField = ::SetDoubleField;
envTable->GetStaticObjectField = ::GetStaticObjectField;
envTable->GetStaticBooleanField = ::GetStaticBooleanField;
envTable->GetStaticByteField = ::GetStaticByteField;
envTable->GetStaticCharField = ::GetStaticCharField;
envTable->GetStaticShortField = ::GetStaticShortField;
envTable->GetStaticIntField = ::GetStaticIntField;
envTable->GetStaticLongField = ::GetStaticLongField;
envTable->GetStaticFloatField = ::GetStaticFloatField;
envTable->GetStaticDoubleField = ::GetStaticDoubleField;
envTable->SetStaticObjectField = ::SetStaticObjectField;
envTable->SetStaticBooleanField = ::SetStaticBooleanField;
envTable->SetStaticByteField = ::SetStaticByteField;
envTable->SetStaticCharField = ::SetStaticCharField;
envTable->SetStaticShortField = ::SetStaticShortField;
envTable->SetStaticIntField = ::SetStaticIntField;
envTable->SetStaticLongField = ::SetStaticLongField;
envTable->SetStaticFloatField = ::SetStaticFloatField;
envTable->SetStaticDoubleField = ::SetStaticDoubleField;
envTable->NewGlobalRef = ::NewGlobalRef;
envTable->DeleteGlobalRef = ::DeleteGlobalRef;
envTable->ExceptionOccurred = ::ExceptionOccurred;
envTable->ExceptionDescribe = ::ExceptionDescribe;
envTable->ExceptionClear = ::ExceptionClear;
envTable->NewBooleanArray = ::NewBooleanArray;
envTable->NewByteArray = ::NewByteArray;
envTable->NewCharArray = ::NewCharArray;
envTable->NewShortArray = ::NewShortArray;
envTable->NewIntArray = ::NewIntArray;
envTable->NewLongArray = ::NewLongArray;
envTable->NewFloatArray = ::NewFloatArray;
envTable->NewDoubleArray = ::NewDoubleArray;
envTable->GetBooleanArrayElements = ::GetBooleanArrayElements;
envTable->GetByteArrayElements = ::GetByteArrayElements;
envTable->GetCharArrayElements = ::GetCharArrayElements;
envTable->GetShortArrayElements = ::GetShortArrayElements;
envTable->GetIntArrayElements = ::GetIntArrayElements;
envTable->GetLongArrayElements = ::GetLongArrayElements;
envTable->GetFloatArrayElements = ::GetFloatArrayElements;
envTable->GetDoubleArrayElements = ::GetDoubleArrayElements;
envTable->ReleaseBooleanArrayElements = ::ReleaseBooleanArrayElements;
envTable->ReleaseByteArrayElements = ::ReleaseByteArrayElements;
envTable->ReleaseCharArrayElements = ::ReleaseCharArrayElements;
envTable->ReleaseShortArrayElements = ::ReleaseShortArrayElements;
envTable->ReleaseIntArrayElements = ::ReleaseIntArrayElements;
envTable->ReleaseLongArrayElements = ::ReleaseLongArrayElements;
envTable->ReleaseFloatArrayElements = ::ReleaseFloatArrayElements;
envTable->ReleaseDoubleArrayElements = ::ReleaseDoubleArrayElements;
envTable->GetBooleanArrayRegion = ::GetBooleanArrayRegion;
envTable->GetByteArrayRegion = ::GetByteArrayRegion;
envTable->GetCharArrayRegion = ::GetCharArrayRegion;
envTable->GetShortArrayRegion = ::GetShortArrayRegion;
envTable->GetIntArrayRegion = ::GetIntArrayRegion;
envTable->GetLongArrayRegion = ::GetLongArrayRegion;
envTable->GetFloatArrayRegion = ::GetFloatArrayRegion;
envTable->GetDoubleArrayRegion = ::GetDoubleArrayRegion;
envTable->GetPrimitiveArrayCritical = ::GetPrimitiveArrayCritical;
envTable->ReleasePrimitiveArrayCritical = ::ReleasePrimitiveArrayCritical;
envTable->GetJavaVM = ::GetJavaVM;
envTable->IsSameObject = ::IsSameObject;
} }
} // namespace vm } // namespace vm

View File

@ -6,7 +6,7 @@
namespace vm { namespace vm {
void void
populateJNITable(JNIEnvVTable* table); populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable);
} // namespace vm } // namespace vm

View File

@ -1268,6 +1268,7 @@ removeString(Thread* t, object o)
namespace vm { namespace vm {
Machine::Machine(System* system, Heap* heap, Finder* finder): Machine::Machine(System* system, Heap* heap, Finder* finder):
vtable(&javaVMVTable),
system(system), system(system),
heap(heap), heap(heap),
finder(finder), finder(finder),
@ -1276,6 +1277,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder):
jniReferences(0), jniReferences(0),
activeCount(0), activeCount(0),
liveCount(0), liveCount(0),
localThread(0),
stateLock(0), stateLock(0),
heapLock(0), heapLock(0),
classLock(0), classLock(0),
@ -1296,9 +1298,10 @@ Machine::Machine(System* system, Heap* heap, Finder* finder):
unsafe(false), unsafe(false),
heapPoolIndex(0) heapPoolIndex(0)
{ {
populateJNITable(&jniEnvVTable); populateJNITables(&javaVMVTable, &jniEnvVTable);
if (not system->success(system->make(&stateLock)) or if (not system->success(system->make(&localThread)) or
not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) or not system->success(system->make(&heapLock)) or
not system->success(system->make(&classLock)) or not system->success(system->make(&classLock)) or
not system->success(system->make(&referenceLock))) not system->success(system->make(&referenceLock)))
@ -1310,6 +1313,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder):
void void
Machine::dispose() Machine::dispose()
{ {
localThread->dispose();
stateLock->dispose(); stateLock->dispose();
heapLock->dispose(); heapLock->dispose();
classLock->dispose(); classLock->dispose();
@ -1430,12 +1434,17 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
populateBuiltinMap(t, m->builtinMap); populateBuiltinMap(t, m->builtinMap);
t->javaThread = makeThread m->localThread->set(this);
(t, reinterpret_cast<int64_t>(t), 0, 0, 0, 0, t->vm->loader);
} else { } else {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
parent->child = this; parent->child = this;
} }
if (javaThread) {
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
} else {
this->javaThread = makeThread
(this, reinterpret_cast<int64_t>(this), 0, 0, 0, 0, m->loader);
}
} }
void void

View File

@ -65,12 +65,14 @@ const unsigned PrimitiveFlag = 1 << 4;
// method flags: // method flags:
const unsigned ClassInitFlag = 1 << 0; const unsigned ClassInitFlag = 1 << 0;
class Machine;
class Thread; class Thread;
struct Object { }; struct Object { };
typedef Object* object; typedef Object* object;
typedef Machine JavaVM;
typedef Thread JNIEnv; typedef Thread JNIEnv;
typedef uint8_t jboolean; typedef uint8_t jboolean;
@ -123,14 +125,6 @@ struct JNINativeMethod {
void* function; void* function;
}; };
struct JavaVMVTable;
struct JavaVM {
JavaVM(JavaVMVTable* vtable): vtable(vtable) { }
JavaVMVTable* vtable;
};
struct JavaVMVTable { struct JavaVMVTable {
void* reserved0; void* reserved0;
void* reserved1; void* reserved1;
@ -142,7 +136,7 @@ struct JavaVMVTable {
jint jint
(JNICALL *AttachCurrentThread) (JNICALL *AttachCurrentThread)
(JavaVM*, void**, void*); (JavaVM*, JNIEnv**, void*);
jint jint
(JNICALL *DetachCurrentThread) (JNICALL *DetachCurrentThread)
@ -150,11 +144,11 @@ struct JavaVMVTable {
jint jint
(JNICALL *GetEnv) (JNICALL *GetEnv)
(JavaVM*, void**, jint); (JavaVM*, JNIEnv**, jint);
jint jint
(JNICALL *AttachCurrentThreadAsDaemon) (JNICALL *AttachCurrentThreadAsDaemon)
(JavaVM*, void**, void*); (JavaVM*, JNIEnv**, void*);
}; };
struct JNIEnvVTable { struct JNIEnvVTable {
@ -1117,6 +1111,7 @@ class Machine {
void dispose(); void dispose();
JavaVMVTable* vtable;
System* system; System* system;
Heap* heap; Heap* heap;
Finder* finder; Finder* finder;
@ -1125,6 +1120,7 @@ class Machine {
Reference* jniReferences; Reference* jniReferences;
unsigned activeCount; unsigned activeCount;
unsigned liveCount; unsigned liveCount;
System::Local* localThread;
System::Monitor* stateLock; System::Monitor* stateLock;
System::Monitor* heapLock; System::Monitor* heapLock;
System::Monitor* classLock; System::Monitor* classLock;
@ -1143,6 +1139,7 @@ class Machine {
object weakReferences; object weakReferences;
object tenuredWeakReferences; object tenuredWeakReferences;
bool unsafe; bool unsafe;
JavaVMVTable javaVMVTable;
JNIEnvVTable jniEnvVTable; JNIEnvVTable jniEnvVTable;
uintptr_t* heapPool[HeapPoolSize]; uintptr_t* heapPool[HeapPoolSize];
unsigned heapPoolIndex; unsigned heapPoolIndex;
@ -1197,6 +1194,8 @@ class Thread {
} }
virtual void run() { virtual void run() {
t->vm->localThread->set(t);
vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread); vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread);
if (t->exception) { if (t->exception) {

View File

@ -349,6 +349,33 @@ class MySystem: public System {
unsigned depth; unsigned depth;
}; };
class Local: public System::Local {
public:
Local(System* s): s(s) {
int r = pthread_key_create(&key, 0);
assert(s, r);
}
virtual void* get() {
return pthread_getspecific(key);
}
virtual void set(void* p) {
int r = pthread_setspecific(key, p);
assert(s, r);
}
virtual void dispose() {
int r = pthread_key_delete(key);
assert(s, r);
s->free(this);
}
System* s;
pthread_key_t key;
};
class Library: public System::Library { class Library: public System::Library {
public: public:
Library(System* s, void* p, const char* name, System::Library* next): Library(System* s, void* p, const char* name, System::Library* next):
@ -475,6 +502,11 @@ class MySystem: public System {
return 0; return 0;
} }
virtual Status make(System::Local** l) {
*l = new (System::allocate(sizeof(Local))) Local(this);
return 0;
}
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size, unsigned returnType) unsigned count, unsigned size, unsigned returnType)
{ {

View File

@ -47,6 +47,14 @@ class System: public Allocator {
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
class Local {
public:
virtual ~Local() { }
virtual void* get() = 0;
virtual void set(void* p) = 0;
virtual void dispose() = 0;
};
class Library { class Library {
public: public:
virtual ~Library() { } virtual ~Library() { }
@ -62,6 +70,7 @@ class System: public Allocator {
virtual Status attach(Runnable*) = 0; virtual Status attach(Runnable*) = 0;
virtual Status start(Runnable*) = 0; virtual Status start(Runnable*) = 0;
virtual Status make(Monitor**) = 0; virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0;
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
unsigned count, unsigned size, unsigned count, unsigned size,
unsigned returnType) = 0; unsigned returnType) = 0;