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_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
#endif//CONSTANTS_H

View File

@ -9,6 +9,45 @@ namespace {
const uintptr_t InterfaceMethodID
= (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
GetStringUTFLength(Thread* t, jstring s)
{
@ -981,6 +1020,70 @@ ExceptionClear(Thread* t)
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
GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
{
@ -1367,9 +1470,10 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
}
jint JNICALL
GetJavaVM(Thread* t, JavaVM** vm)
GetJavaVM(Thread* t, Machine** m)
{
#warning todo
*m = t->vm;
return 0;
}
jboolean JNICALL
@ -1377,7 +1481,7 @@ IsSameObject(Thread* t, jobject a, jobject b)
{
ENTER(t, Thread::ActiveState);
return a == b;
return *a == *b;
}
} // namespace
@ -1385,60 +1489,149 @@ IsSameObject(Thread* t, jobject a, jobject b)
namespace vm {
void
populateJNITable(JNIEnvVTable* table)
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
{
memset(table, 0, sizeof(JNIEnvVTable));
memset(vmTable, 0, sizeof(JavaVMVTable));
table->GetStringUTFLength = ::GetStringUTFLength;
table->GetStringUTFChars = ::GetStringUTFChars;
table->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
table->NewStringUTF = ::NewStringUTF;
table->GetByteArrayRegion = ::GetByteArrayRegion;
table->SetByteArrayRegion = ::SetByteArrayRegion;
table->FindClass = ::FindClass;
table->ThrowNew = ::ThrowNew;
table->ExceptionCheck = ::ExceptionCheck;
table->DeleteLocalRef = ::DeleteLocalRef;
table->GetObjectClass = ::GetObjectClass;
table->IsInstanceOf = ::IsInstanceOf;
table->GetFieldID = ::GetFieldID;
table->GetStaticFieldID = ::GetStaticFieldID;
table->GetObjectField = ::GetObjectField;
table->GetBooleanField = ::GetBooleanField;
table->GetByteField = ::GetByteField;
table->GetCharField = ::GetCharField;
table->GetShortField = ::GetShortField;
table->GetIntField = ::GetIntField;
table->GetLongField = ::GetLongField;
table->GetFloatField = ::GetFloatField;
table->GetDoubleField = ::GetDoubleField;
table->SetObjectField = ::SetObjectField;
table->SetBooleanField = ::SetBooleanField;
table->SetByteField = ::SetByteField;
table->SetCharField = ::SetCharField;
table->SetShortField = ::SetShortField;
table->SetIntField = ::SetIntField;
table->SetLongField = ::SetLongField;
table->SetFloatField = ::SetFloatField;
table->SetDoubleField = ::SetDoubleField;
table->GetStaticObjectField = ::GetStaticObjectField;
table->GetStaticBooleanField = ::GetStaticBooleanField;
table->GetStaticByteField = ::GetStaticByteField;
table->GetStaticCharField = ::GetStaticCharField;
table->GetStaticShortField = ::GetStaticShortField;
table->GetStaticIntField = ::GetStaticIntField;
table->GetStaticLongField = ::GetStaticLongField;
table->GetStaticFloatField = ::GetStaticFloatField;
table->GetStaticDoubleField = ::GetStaticDoubleField;
table->SetStaticObjectField = ::SetStaticObjectField;
table->SetStaticBooleanField = ::SetStaticBooleanField;
table->SetStaticByteField = ::SetStaticByteField;
table->SetStaticCharField = ::SetStaticCharField;
table->SetStaticShortField = ::SetStaticShortField;
table->SetStaticIntField = ::SetStaticIntField;
table->SetStaticLongField = ::SetStaticLongField;
table->SetStaticFloatField = ::SetStaticFloatField;
table->SetStaticDoubleField = ::SetStaticDoubleField;
vmTable->AttachCurrentThread = AttachCurrentThread;
vmTable->DetachCurrentThread = DetachCurrentThread;
vmTable->GetEnv = GetEnv;
memset(envTable, 0, sizeof(JNIEnvVTable));
envTable->GetStringUTFLength = ::GetStringUTFLength;
envTable->GetStringUTFChars = ::GetStringUTFChars;
envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars;
envTable->NewStringUTF = ::NewStringUTF;
envTable->GetByteArrayRegion = ::GetByteArrayRegion;
envTable->SetByteArrayRegion = ::SetByteArrayRegion;
envTable->FindClass = ::FindClass;
envTable->ThrowNew = ::ThrowNew;
envTable->ExceptionCheck = ::ExceptionCheck;
envTable->DeleteLocalRef = ::DeleteLocalRef;
envTable->GetObjectClass = ::GetObjectClass;
envTable->IsInstanceOf = ::IsInstanceOf;
envTable->GetFieldID = ::GetFieldID;
envTable->GetMethodID = ::GetMethodID;
envTable->GetStaticMethodID = ::GetStaticMethodID;
envTable->CallObjectMethodV = ::CallObjectMethodV;
envTable->CallObjectMethod = ::CallObjectMethod;
envTable->CallBooleanMethodV = ::CallBooleanMethodV;
envTable->CallBooleanMethod = ::CallBooleanMethod;
envTable->CallByteMethodV = ::CallByteMethodV;
envTable->CallByteMethod = ::CallByteMethod;
envTable->CallCharMethodV = ::CallCharMethodV;
envTable->CallCharMethod = ::CallCharMethod;
envTable->CallShortMethodV = ::CallShortMethodV;
envTable->CallShortMethod = ::CallShortMethod;
envTable->CallIntMethodV = ::CallIntMethodV;
envTable->CallIntMethod = ::CallIntMethod;
envTable->CallLongMethodV = ::CallLongMethodV;
envTable->CallLongMethod = ::CallLongMethod;
envTable->CallFloatMethodV = ::CallFloatMethodV;
envTable->CallFloatMethod = ::CallFloatMethod;
envTable->CallDoubleMethodV = ::CallDoubleMethodV;
envTable->CallDoubleMethod = ::CallDoubleMethod;
envTable->CallVoidMethodV = ::CallVoidMethodV;
envTable->CallVoidMethod = ::CallVoidMethod;
envTable->CallStaticObjectMethodV = ::CallStaticObjectMethodV;
envTable->CallStaticObjectMethod = ::CallStaticObjectMethod;
envTable->CallStaticBooleanMethodV = ::CallStaticBooleanMethodV;
envTable->CallStaticBooleanMethod = ::CallStaticBooleanMethod;
envTable->CallStaticByteMethodV = ::CallStaticByteMethodV;
envTable->CallStaticByteMethod = ::CallStaticByteMethod;
envTable->CallStaticCharMethodV = ::CallStaticCharMethodV;
envTable->CallStaticCharMethod = ::CallStaticCharMethod;
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

View File

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

View File

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

View File

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

View File

@ -349,6 +349,33 @@ class MySystem: public System {
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 {
public:
Library(System* s, void* p, const char* name, System::Library* next):
@ -475,6 +502,11 @@ class MySystem: public System {
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,
unsigned count, unsigned size, unsigned returnType)
{

View File

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