Fix LDC, LDC_W, and INSTANCEOF opcodes, more debugging
[jamvm-avr32-jem.git] / src / jni.c
blob917c210731cdbe874ad8631b9f7f33f05d7210b9
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #ifndef NO_JNI
23 #include <string.h>
24 #include <stdlib.h>
25 #include "jni.h"
26 #include "jam.h"
27 #include "thread.h"
28 #include "lock.h"
30 #define JNI_VERSION JNI_VERSION_1_4
32 /* The extra used in expanding the local refs table.
33 * This must be >= size of JNIFrame to be thread safe
34 * wrt GC thread suspension */
35 #define LIST_INCR 8
37 /* The amount of local reference space "ensured" before
38 entering a JNI method. The method is garaunteed to
39 be able to create this amount without failure */
40 #define JNI_DEFAULT_LREFS 16
42 /* Forward declarations */
43 const jchar *Jam_GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
44 void Jam_ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);
45 jobject Jam_NewGlobalRef(JNIEnv *env, jobject obj);
46 void Jam_DeleteGlobalRef(JNIEnv *env, jobject obj);
47 JNIFrame *ensureJNILrefCapacity(int cap);
48 static void initJNIGrefs();
50 /* Cached values initialised on startup for JNI 1.4 NIO support */
51 static int buffCap_offset, buffAddr_offset, rawdata_offset;
52 static Class *buffImpl_class, *rawdata_class;
53 static MethodBlock *buffImpl_init_mb;
54 static char nio_init_OK = FALSE;
56 void initialiseJNI() {
57 FieldBlock *buffCap_fb, *buffAddr_fb, *rawdata_fb;
58 Class *buffer_class;
60 /* Initialise the global references table */
61 initJNIGrefs();
63 /* Cache class and method/fields for JNI 1.4 NIO support */
65 buffer_class = findSystemClass0("java/nio/Buffer");
66 buffImpl_class = findSystemClass0("java/nio/DirectByteBufferImpl");
67 rawdata_class = findSystemClass0(sizeof(uintptr_t) == 4 ? "gnu/classpath/Pointer32"
68 : "gnu/classpath/Pointer64");
70 buffImpl_init_mb = findMethod(buffImpl_class, "<init>",
71 "(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V");
73 buffCap_fb = findField(buffer_class, "cap", "I");
74 rawdata_fb = findField(rawdata_class, "data", sizeof(uintptr_t) == 4 ? "I" : "J");
75 buffAddr_fb = findField(buffer_class, "address", "Lgnu/classpath/Pointer;");
77 if(buffImpl_init_mb == NULL || buffCap_fb == NULL ||
78 rawdata_fb == NULL || buffAddr_fb == NULL) {
79 return;
82 registerStaticClassRef(&buffImpl_class);
83 registerStaticClassRef(&rawdata_class);
85 buffCap_offset = buffCap_fb->offset;
86 buffAddr_offset = buffAddr_fb->offset;
87 rawdata_offset = rawdata_fb->offset;
88 nio_init_OK = TRUE;
91 int initJNILrefs() {
92 JNIFrame *frame = ensureJNILrefCapacity(JNI_DEFAULT_LREFS);
94 if(frame != NULL) {
95 frame->next_ref = frame->lrefs + frame->mb->args_count;
96 return TRUE;
99 return FALSE;
102 JNIFrame *expandJNILrefs(ExecEnv *ee, JNIFrame *frame, int incr) {
103 JNIFrame *new_frame = (JNIFrame*)((Object**)frame + incr);
105 if((char*)(new_frame + 1) > ee->stack_end)
106 return NULL;
108 memcpy(new_frame, frame, sizeof(JNIFrame));
109 new_frame->ostack = (uintptr_t*)(new_frame + 1);
110 ee->last_frame = (Frame*)new_frame;
111 memset(frame, 0, incr * sizeof(Object*));
112 return new_frame;
115 JNIFrame *ensureJNILrefCapacity(int cap) {
116 ExecEnv *ee = getExecEnv();
117 JNIFrame *frame = (JNIFrame*)ee->last_frame;
118 int size = (Object**)frame - frame->lrefs - frame->mb->args_count;
120 if(size < cap) {
121 int incr = cap-size;
122 if(incr < sizeof(JNIFrame)/sizeof(Object*))
123 incr = sizeof(JNIFrame)/sizeof(Object*);
125 if((frame = expandJNILrefs(ee, frame, incr)) == NULL)
126 signalException("java/lang/OutOfMemoryError", "JNI local references");
129 return frame;
132 Object *addJNILref(Object *ref) {
133 ExecEnv *ee = getExecEnv();
134 JNIFrame *frame = (JNIFrame*)ee->last_frame;
136 if(ref == NULL)
137 return NULL;
139 if(frame->next_ref == (Object**)frame)
140 if((frame = expandJNILrefs(ee, frame, LIST_INCR)) == NULL) {
141 jam_fprintf(stderr, "JNI - FatalError: cannot expand local references.\n");
142 exitVM(1);
145 return *frame->next_ref++ = ref;
148 void delJNILref(Object *ref) {
149 ExecEnv *ee = getExecEnv();
150 JNIFrame *frame = (JNIFrame*)ee->last_frame;
151 Object **opntr = frame->lrefs;
153 for(; opntr < frame->next_ref; opntr++)
154 if(*opntr == ref) {
155 *opntr = NULL;
156 return;
160 JNIFrame *pushJNILrefFrame(int cap) {
161 ExecEnv *ee = getExecEnv();
162 JNIFrame *frame = (JNIFrame*)ee->last_frame;
163 JNIFrame *new_frame = (JNIFrame*)((Object**)(frame + 1) + cap);
165 if((char*)(new_frame + 1) > ee->stack_end) {
166 signalException("java/lang/OutOfMemoryError", "JNI local references");
167 return NULL;
170 new_frame->lrefs = new_frame->next_ref = (Object**)(frame + 1);
171 new_frame->ostack = (uintptr_t*)(new_frame + 1);
172 new_frame->prev = frame->prev;
173 new_frame->mb = frame->mb;
175 memset(frame + 1, 0, cap * sizeof(Object*));
176 ee->last_frame = (Frame*)new_frame;
178 return new_frame;
181 void popJNILrefFrame() {
182 ExecEnv *ee = getExecEnv();
183 JNIFrame *frame = (JNIFrame*)ee->last_frame;
184 JNIFrame *prev = (JNIFrame*)frame->lrefs - 1;
186 ee->last_frame = (Frame*)prev;
189 static VMLock global_ref_lock;
190 static Object **global_ref_table;
191 static int global_ref_size = 0;
192 static int global_ref_next = 0;
193 static int global_ref_deleted = 0;
195 static void initJNIGrefs() {
196 initVMLock(global_ref_lock);
199 static Object *addJNIGref(Object *ref) {
200 Thread *self = threadSelf();
201 disableSuspend(self);
202 lockVMLock(global_ref_lock, self);
204 if(global_ref_next == global_ref_size) {
205 int new_size;
206 Object **new_table;
207 int i, j;
209 if(global_ref_deleted >= LIST_INCR) {
210 new_size = global_ref_size;
211 new_table = global_ref_table;
212 } else {
213 new_size = global_ref_size + LIST_INCR - global_ref_deleted;
214 new_table = (Object**)sysMalloc(new_size * sizeof(Object*));
217 for(i = 0, j = 0; i < global_ref_size; i++)
218 if(global_ref_table[i])
219 new_table[j++] = global_ref_table[i];
221 global_ref_next = j;
222 global_ref_size = new_size;
223 global_ref_table = new_table;
224 global_ref_deleted = 0;
227 global_ref_table[global_ref_next++] = ref;
229 unlockVMLock(global_ref_lock, self);
230 enableSuspend(self);
232 return ref;
235 static void delJNIGref(Object *ref) {
236 Thread *self = threadSelf();
237 int i;
239 disableSuspend(self);
240 lockVMLock(global_ref_lock, self);
242 for(i = 0; i < global_ref_next; i++)
243 if(global_ref_table[i] == ref) {
244 global_ref_table[i] = NULL;
245 global_ref_deleted++;
246 break;
249 unlockVMLock(global_ref_lock, self);
250 enableSuspend(self);
253 /* Called during mark phase of GC. Safe from
254 suspension but must grab lock to ensure list
255 isn't being modified by another thread. */
257 void markJNIGlobalRefs() {
258 Thread *self = threadSelf();
259 int i;
261 lockVMLock(global_ref_lock, self);
263 for(i = 0; i < global_ref_next; i++)
264 if(global_ref_table[i])
265 markConservativeRoot(global_ref_table[i]);
267 unlockVMLock(global_ref_lock, self);
270 /* Extensions added to JNI in JDK 1.4 */
272 jobject Jam_NewDirectByteBuffer(JNIEnv *env, void *addr, jlong capacity) {
273 Object *buff, *rawdata;
275 if(!nio_init_OK)
276 return NULL;
278 if((buff = allocObject(buffImpl_class)) != NULL &&
279 (rawdata = allocObject(rawdata_class)) != NULL) {
281 INST_DATA(rawdata)[rawdata_offset] = (uintptr_t)addr;
282 executeMethod(buff, buffImpl_init_mb, NULL, rawdata, (int)capacity,
283 (int)capacity, 0);
286 return (jobject) addJNILref(buff);
289 static void *Jam_GetDirectBufferAddress(JNIEnv *env, jobject buffer) {
290 Object *buff = (Object*)buffer;
292 if(!nio_init_OK)
293 return NULL;
295 if(buff != NULL) {
296 Object *rawdata = (Object *)INST_DATA(buff)[buffAddr_offset];
297 if(rawdata != NULL)
298 return (void*)INST_DATA(rawdata)[rawdata_offset];
301 return NULL;
304 jlong Jam_GetDirectBufferCapacity(JNIEnv *env, jobject buffer) {
305 Object *buff = (Object*)buffer;
307 if(!nio_init_OK)
308 return -1;
310 if(buff != NULL) {
311 Object *rawdata = (Object *)INST_DATA(buff)[buffAddr_offset];
312 if(rawdata != NULL)
313 return (jlong)INST_DATA(buff)[buffCap_offset];
316 return -1;
319 /* Extensions added to JNI in JDK 1.2 */
321 jmethodID Jam_FromReflectedMethod(JNIEnv *env, jobject method) {
322 return mbFromReflectObject((Object*)method);
325 jfieldID Jam_FromReflectedField(JNIEnv *env, jobject field) {
326 return fbFromReflectObject((Object*)field);
329 jobject Jam_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic) {
330 MethodBlock *mb = (MethodBlock *)methodID;
331 if(strcmp(mb->name, "<init>") == 0)
332 return (jobject) createReflectConstructorObject(mb);
333 else
334 return (jobject) createReflectMethodObject(mb);
337 jobject Jam_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic) {
338 return (jobject) createReflectFieldObject((FieldBlock *)fieldID);
341 jint Jam_PushLocalFrame(JNIEnv *env, jint capacity) {
342 return pushJNILrefFrame(capacity) == NULL ? JNI_ERR : JNI_OK;
345 jobject Jam_PopLocalFrame(JNIEnv *env, jobject result) {
346 popJNILrefFrame();
347 return addJNILref(result);
350 jobject Jam_NewLocalRef(JNIEnv *env, jobject obj) {
351 return addJNILref(obj);
354 jint Jam_EnsureLocalCapacity(JNIEnv *env, jint capacity) {
355 return ensureJNILrefCapacity(capacity) == NULL ? JNI_ERR : JNI_OK;
358 void Jam_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf) {
359 if((start + len) > getStringLen((Object*)string))
360 signalException("java/lang/StringIndexOutOfBoundsException", NULL);
361 else
362 memcpy(buf, getStringChars((Object*)string) + start, len * sizeof(short));
365 void Jam_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf) {
366 if((start + len) > getStringLen((Object*)string))
367 signalException("java/lang/StringIndexOutOfBoundsException", NULL);
368 else
369 StringRegion2Utf8((Object*)string, start, len, buf);
372 void *Jam_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) {
373 if(isCopy != NULL)
374 *isCopy = JNI_FALSE;
375 addJNIGref((Object*)array);
376 return ARRAY_DATA((Object*)array);
379 void Jam_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode) {
380 delJNIGref((Object*)array);
383 const jchar *Jam_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) {
384 return Jam_GetStringChars(env, string, isCopy);
387 void Jam_ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *chars) {
388 Jam_ReleaseStringChars(env, string, chars);
391 jweak Jam_NewWeakGlobalRef(JNIEnv *env, jobject obj) {
392 return Jam_NewGlobalRef(env, obj);
395 void Jam_DeleteWeakGlobalRef(JNIEnv *env, jweak obj) {
396 Jam_DeleteGlobalRef(env, obj);
399 jboolean Jam_ExceptionCheck(JNIEnv *env) {
400 return exceptionOccurred() ? JNI_TRUE : JNI_FALSE;
403 /* JNI 1.1 interface */
405 jint Jam_GetVersion(JNIEnv *env) {
406 return JNI_VERSION;
409 jclass Jam_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen) {
410 return (jclass)defineClass((char*)name, (char *)buf, 0, (int)bufLen, (Object *)loader);
413 jclass Jam_FindClass(JNIEnv *env, const char *name) {
414 /* We use the class loader associated with the calling native method.
415 However, if this has been called from an attached thread there may
416 be no native Java frame. In this case use the system class loader */
417 Frame *last = getExecEnv()->last_frame;
418 Object *loader = last->prev ? CLASS_CB(last->mb->class)->class_loader
419 : getSystemClassLoader();
421 return (jclass) findClassFromClassLoader((char*) name, loader);
424 jclass Jam_GetSuperClass(JNIEnv *env, jclass clazz) {
425 ClassBlock *cb = CLASS_CB((Class *)clazz);
426 return IS_INTERFACE(cb) ? NULL : (jclass)cb->super;
429 jboolean Jam_IsAssignableFrom(JNIEnv *env, jclass clazz1, jclass clazz2) {
430 return isInstanceOf((Class*)clazz2, (Class*)clazz1);
433 jint Jam_Throw(JNIEnv *env, jthrowable obj) {
434 Object *ob = (Object*)obj;
435 setStackTrace();
436 setException(ob);
437 return JNI_TRUE;
440 jint Jam_ThrowNew(JNIEnv *env, jclass clazz, const char *message) {
441 signalException(CLASS_CB((Class*)clazz)->name, (char*)message);
442 return JNI_TRUE;
445 jthrowable Jam_ExceptionOccurred(JNIEnv *env) {
446 return (jthrowable) addJNILref(exceptionOccurred());
449 void Jam_ExceptionDescribe(JNIEnv *env) {
450 printException();
453 void Jam_ExceptionClear(JNIEnv *env) {
454 clearException();
457 void Jam_FatalError(JNIEnv *env, const char *message) {
458 jam_fprintf(stderr, "JNI - FatalError: %s\n", message);
459 exitVM(1);
462 jobject Jam_NewGlobalRef(JNIEnv *env, jobject obj) {
463 return addJNIGref((Object*)obj);
466 void Jam_DeleteGlobalRef(JNIEnv *env, jobject obj) {
467 delJNIGref((Object*)obj);
470 void Jam_DeleteLocalRef(JNIEnv *env, jobject obj) {
471 delJNILref((Object*)obj);
474 jboolean Jam_IsSameObject(JNIEnv *env, jobject obj1, jobject obj2) {
475 return obj1 == obj2;
478 jobject Jam_AllocObject(JNIEnv *env, jclass clazz) {
479 return (jobject) addJNILref(allocObject((Class*)clazz));
482 jclass Jam_GetObjectClass(JNIEnv *env, jobject obj) {
483 return (jobject)((Object*)obj)->class;
486 jboolean Jam_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) {
487 return (obj == NULL) || isInstanceOf((Class*)clazz, ((Object*)obj)->class);
490 jmethodID Jam_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
491 Class *class = initClass((Class *)clazz);
492 MethodBlock *mb = lookupMethod(class, (char*)name, (char*)sig);
494 if(mb == NULL)
495 signalException("java/lang/NoSuchMethodError", (char *)name);
497 return (jmethodID) mb;
500 jfieldID Jam_GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
501 Class *class = initClass((Class *)clazz);
502 FieldBlock *fb = lookupField(class, (char*)name, (char*)sig);
504 if(fb == NULL)
505 signalException("java/lang/NoSuchFieldError", (char *)name);
507 return (jfieldID) fb;
510 jmethodID Jam_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
511 Class *class = initClass((Class *)clazz);
512 MethodBlock *mb = findMethod(class, (char*)name, (char*)sig);
514 if(mb == NULL)
515 signalException("java/lang/NoSuchMethodError", (char *)name);
517 return (jmethodID) mb;
520 jfieldID Jam_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
521 Class *class = initClass((Class *)clazz);
522 FieldBlock *fb = findField(class, (char*)name, (char*)sig);
524 if(fb == NULL)
525 signalException("java/lang/NoSuchFieldError", (char *)name);
527 return (jfieldID) fb;
530 jstring Jam_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) {
531 return (jstring) addJNILref(createStringFromUnicode((unsigned short*)unicodeChars, len));
534 jsize Jam_GetStringLength(JNIEnv *env, jstring string) {
535 return getStringLen((Object*)string);
538 const jchar *Jam_GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy) {
539 if(isCopy != NULL)
540 *isCopy = JNI_FALSE;
542 /* Pin the reference */
543 addJNIGref(getStringCharsArray((Object*)string));
545 return (const jchar *)getStringChars((Object*)string);
548 void Jam_ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars) {
549 /* Unpin the reference */
550 delJNIGref(getStringCharsArray((Object*)string));
553 jstring Jam_NewStringUTF(JNIEnv *env, const char *bytes) {
554 return (jstring) addJNILref(createString((char*)bytes));
557 jsize Jam_GetStringUTFLength(JNIEnv *env, jstring string) {
558 if(string == NULL)
559 return 0;
560 return getStringUtf8Len((Object*)string);
563 const char *Jam_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) {
564 if(isCopy != NULL)
565 *isCopy = JNI_TRUE;
567 if(string == NULL)
568 return NULL;
569 return (const char*)String2Utf8((Object*)string);
572 void Jam_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *chars) {
573 sysFree((void*)chars);
576 jsize Jam_GetArrayLength(JNIEnv *env, jarray array) {
577 return ARRAY_LEN((Object*)array);
580 jobject Jam_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
581 Object *ob = allocObject((Class*)clazz);
583 if(ob) {
584 va_list jargs;
585 va_start(jargs, methodID);
586 executeMethodVaList(ob, ob->class, (MethodBlock*)methodID, jargs);
587 va_end(jargs);
590 return (jobject) addJNILref(ob);
593 jobject Jam_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) {
594 Object *ob = allocObject((Class*)clazz);
596 if(ob) executeMethodList(ob, ob->class, (MethodBlock*)methodID, (u8*)args);
597 return (jobject) addJNILref(ob);
600 jobject Jam_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) {
601 Object *ob = allocObject((Class*)clazz);
603 if(ob) executeMethodVaList(ob, ob->class, (MethodBlock*)methodID, args);
604 return (jobject) addJNILref(ob);
607 jarray Jam_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) {
608 char *element_name = CLASS_CB((Class*)elementClass)->name;
609 char ac_name[strlen(element_name) + 4];
610 Class *array_class;
612 if(length < 0) {
613 signalException("java/lang/NegativeArraySizeException", NULL);
614 return NULL;
617 if(element_name[0] == '[')
618 strcat(strcpy(ac_name, "["), element_name);
619 else
620 strcat(strcat(strcpy(ac_name, "[L"), element_name), ";");
622 array_class = findArrayClassFromClass(ac_name, (Class*)elementClass);
623 if(array_class != NULL) {
624 Object *array = allocArray(array_class, length, sizeof(Object*));
625 if(array != NULL) {
626 if(initialElement != NULL) {
627 Object **data = ARRAY_DATA(array);
629 while(length--)
630 *data++ = (Object*) initialElement;
632 return (jarray) addJNILref(array);
635 return NULL;
638 jarray Jam_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) {
639 return (jarray) addJNILref(((Object**)ARRAY_DATA((Object*)array))[index]);
642 void Jam_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value) {
643 ((Object**)ARRAY_DATA((Object*)array))[index] = (Object*)value;
646 jint Jam_RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods) {
647 return JNI_OK;
650 jint Jam_UnregisterNatives(JNIEnv *env, jclass clazz) {
651 return JNI_OK;
654 jint Jam_MonitorEnter(JNIEnv *env, jobject obj) {
655 objectLock((Object*)obj);
656 return JNI_OK;
659 jint Jam_MonitorExit(JNIEnv *env, jobject obj) {
660 objectUnlock((Object*)obj);
661 return JNI_OK;
664 struct _JNIInvokeInterface Jam_JNIInvokeInterface;
665 JavaVM invokeIntf = &Jam_JNIInvokeInterface;
667 jint Jam_GetJavaVM(JNIEnv *env, JavaVM **vm) {
668 *vm = &invokeIntf;
669 return JNI_OK;
672 #define GET_FIELD(type, native_type) \
673 native_type Jam_Get##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID) { \
674 FieldBlock *fb = (FieldBlock *) fieldID; \
675 Object *ob = (Object*) obj; \
676 return *(native_type *)&(INST_DATA(ob)[fb->offset]); \
679 #define INT_GET_FIELD(type, native_type) \
680 native_type Jam_Get##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID) { \
681 FieldBlock *fb = (FieldBlock *) fieldID; \
682 Object *ob = (Object*) obj; \
683 return (native_type)(INST_DATA(ob)[fb->offset]); \
686 #define SET_FIELD(type, native_type) \
687 void Jam_Set##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID, native_type value) { \
688 Object *ob = (Object*) obj; \
689 FieldBlock *fb = (FieldBlock *) fieldID; \
690 *(native_type *)&(INST_DATA(ob)[fb->offset]) = value; \
693 #define INT_SET_FIELD(type, native_type) \
694 void Jam_Set##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID, native_type value) { \
695 Object *ob = (Object*) obj; \
696 FieldBlock *fb = (FieldBlock *) fieldID; \
697 INST_DATA(ob)[fb->offset] = (intptr_t)value; \
700 #define GET_STATIC_FIELD(type, native_type) \
701 native_type Jam_GetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID) { \
702 FieldBlock *fb = (FieldBlock *) fieldID; \
703 return *(native_type *)&fb->static_value; \
706 #define INT_GET_STATIC_FIELD(type, native_type) \
707 native_type Jam_GetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID) { \
708 FieldBlock *fb = (FieldBlock *) fieldID; \
709 return (native_type)fb->static_value; \
712 #define SET_STATIC_FIELD(type, native_type) \
713 void Jam_SetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, \
714 native_type value) { \
715 FieldBlock *fb = (FieldBlock *) fieldID; \
716 *(native_type *)&fb->static_value = value; \
719 #define INT_SET_STATIC_FIELD(type, native_type) \
720 void Jam_SetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, \
721 native_type value) { \
722 FieldBlock *fb = (FieldBlock *) fieldID; \
723 fb->static_value = (intptr_t)value; \
726 #define FIELD_ACCESS(type, native_type) \
727 GET_FIELD(type, native_type); \
728 SET_FIELD(type, native_type); \
729 GET_STATIC_FIELD(type, native_type); \
730 SET_STATIC_FIELD(type, native_type);
732 #define INT_FIELD_ACCESS(type, native_type) \
733 INT_GET_FIELD(type, native_type); \
734 INT_SET_FIELD(type, native_type); \
735 INT_GET_STATIC_FIELD(type, native_type); \
736 INT_SET_STATIC_FIELD(type, native_type);
738 INT_FIELD_ACCESS(Boolean, jboolean);
739 INT_FIELD_ACCESS(Byte, jbyte);
740 INT_FIELD_ACCESS(Char, jchar);
741 INT_FIELD_ACCESS(Short, jshort);
742 INT_FIELD_ACCESS(Int, jint);
743 FIELD_ACCESS(Long, jlong);
744 FIELD_ACCESS(Float, jfloat);
745 FIELD_ACCESS(Double, jdouble);
747 jobject Jam_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) {
748 FieldBlock *fb = (FieldBlock *) fieldID;
749 Object *ob = (Object*) obj;
750 return (jobject) addJNILref((Object*)(INST_DATA(ob)[fb->offset]));
753 void Jam_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) {
754 Object *ob = (Object*) obj;
755 FieldBlock *fb = (FieldBlock *) fieldID;
756 INST_DATA(ob)[fb->offset] = (uintptr_t)value;
759 jobject Jam_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
760 FieldBlock *fb = (FieldBlock *) fieldID;
761 return (jobject) addJNILref((Object*)fb->static_value);
764 void Jam_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) {
765 FieldBlock *fb = (FieldBlock *) fieldID;
766 fb->static_value = (uintptr_t)value;
769 #define VIRTUAL_METHOD(type, native_type) \
770 native_type Jam_Call##type##Method(JNIEnv *env, jobject obj, jmethodID mID, ...) { \
771 Object *ob = (Object *)obj; \
772 native_type *ret; \
773 va_list jargs; \
775 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
776 if(mb == NULL) \
777 return (native_type)0; \
779 va_start(jargs, mID); \
780 ret = (native_type*) executeMethodVaList(ob, ob->class, mb, jargs); \
781 va_end(jargs); \
783 return *ret; \
786 native_type Jam_Call##type##MethodV(JNIEnv *env, jobject obj, jmethodID mID, va_list jargs) { \
787 Object *ob = (Object *)obj; \
788 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
789 return mb == NULL ? (native_type)0 : \
790 *(native_type*)executeMethodVaList(ob, ob->class, mb, jargs); \
793 native_type Jam_Call##type##MethodA(JNIEnv *env, jobject obj, jmethodID mID, jvalue *jargs) { \
794 Object *ob = (Object *)obj; \
795 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
796 return mb == NULL ? (native_type)0 : \
797 *(native_type*)executeMethodList(ob, ob->class, mb, (u8*)jargs); \
800 #define INT_VIRTUAL_METHOD(type, native_type) \
801 native_type Jam_Call##type##Method(JNIEnv *env, jobject obj, jmethodID mID, ...) { \
802 Object *ob = (Object *)obj; \
803 uintptr_t *ret; \
804 va_list jargs; \
806 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
807 if(mb == NULL) \
808 return (native_type)0; \
810 va_start(jargs, mID); \
811 ret = executeMethodVaList(ob, ob->class, mb, jargs); \
812 va_end(jargs); \
814 return (native_type)*ret; \
817 native_type Jam_Call##type##MethodV(JNIEnv *env, jobject obj, jmethodID mID, va_list jargs) { \
818 Object *ob = (Object *)obj; \
819 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
820 return mb == NULL ? (native_type)0 : \
821 (native_type)*(uintptr_t*)executeMethodVaList(ob, ob->class, mb, jargs); \
824 native_type Jam_Call##type##MethodA(JNIEnv *env, jobject obj, jmethodID mID, jvalue *jargs) { \
825 Object *ob = (Object *)obj; \
826 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
827 return mb == NULL ? (native_type)0 : (native_type)*(uintptr_t*) \
828 executeMethodList(ob, ob->class, mb, (u8*)jargs); \
831 #define NONVIRTUAL_METHOD(type, native_type) \
832 native_type Jam_CallNonvirtual##type##Method(JNIEnv *env, jobject obj, jclass clazz, \
833 jmethodID methodID, ...) { \
834 native_type *ret; \
835 va_list jargs; \
837 va_start(jargs, methodID); \
838 ret = (native_type*) \
839 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
840 va_end(jargs); \
842 return *ret; \
845 native_type Jam_CallNonvirtual##type##MethodV(JNIEnv *env, jobject obj, jclass clazz, \
846 jmethodID methodID, va_list jargs) { \
847 return *(native_type*) \
848 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
851 native_type Jam_CallNonvirtual##type##MethodA(JNIEnv *env, jobject obj, jclass clazz, \
852 jmethodID methodID, jvalue *jargs) { \
853 return *(native_type*) \
854 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
857 #define INT_NONVIRTUAL_METHOD(type, native_type) \
858 native_type Jam_CallNonvirtual##type##Method(JNIEnv *env, jobject obj, jclass clazz, \
859 jmethodID methodID, ...) { \
860 uintptr_t *ret; \
861 va_list jargs; \
863 va_start(jargs, methodID); \
864 ret = executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
865 va_end(jargs); \
867 return (native_type)*ret; \
870 native_type Jam_CallNonvirtual##type##MethodV(JNIEnv *env, jobject obj, jclass clazz, \
871 jmethodID methodID, va_list jargs) { \
872 return (native_type)*(uintptr_t*) \
873 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
876 native_type Jam_CallNonvirtual##type##MethodA(JNIEnv *env, jobject obj, jclass clazz, \
877 jmethodID methodID, jvalue *jargs) { \
878 return (native_type)*(uintptr_t*) \
879 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
882 #define STATIC_METHOD(type, native_type) \
883 native_type Jam_CallStatic##type##Method(JNIEnv *env, jclass clazz, \
884 jmethodID methodID, ...) { \
885 native_type *ret; \
886 va_list jargs; \
888 va_start(jargs, methodID); \
889 ret = (native_type*) executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);\
890 va_end(jargs); \
892 return *ret; \
895 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
896 va_list jargs) { \
897 return *(native_type*) \
898 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
901 native_type Jam_CallStatic##type##MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, \
902 jvalue *jargs) { \
903 return *(native_type*) \
904 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
907 #define INT_STATIC_METHOD(type, native_type) \
908 native_type Jam_CallStatic##type##Method(JNIEnv *env, jclass clazz, \
909 jmethodID methodID, ...) { \
910 uintptr_t *ret; \
911 va_list jargs; \
913 va_start(jargs, methodID); \
914 ret = executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
915 va_end(jargs); \
917 return (native_type)*ret; \
920 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
921 va_list jargs) { \
922 return (native_type) *(uintptr_t*) \
923 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
926 native_type Jam_CallStatic##type##MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, \
927 jvalue *jargs) { \
928 return (native_type)*(uintptr_t*) \
929 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
932 #define CALL_METHOD(access) \
933 INT_##access##_METHOD(Boolean, jboolean); \
934 INT_##access##_METHOD(Byte, jbyte); \
935 INT_##access##_METHOD(Char, jchar); \
936 INT_##access##_METHOD(Short, jshort); \
937 INT_##access##_METHOD(Int, jint); \
938 access##_METHOD(Long, jlong); \
939 access##_METHOD(Float, jfloat); \
940 access##_METHOD(Double, jdouble);
942 CALL_METHOD(VIRTUAL);
943 CALL_METHOD(NONVIRTUAL);
944 CALL_METHOD(STATIC);
946 jobject Jam_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
947 Object *ob = (Object *)obj;
948 Object *ret;
949 va_list jargs;
950 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
951 if(mb == NULL)
952 return NULL;
954 va_start(jargs, methodID);
955 ret = addJNILref(*(Object**) executeMethodVaList(ob, ob->class, mb, jargs));
956 va_end(jargs);
957 return (jobject)ret;
960 jobject Jam_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list jargs) {
961 Object *ob = (Object *)obj;
962 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
964 return mb == NULL ? NULL : (jobject)addJNILref(*(Object**)
965 executeMethodVaList(ob, ob->class, mb, jargs));
968 jobject Jam_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *jargs) {
969 Object *ob = (Object *)obj;
970 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
972 return mb == NULL ? NULL : (jobject)addJNILref(*(Object**)
973 executeMethodList(ob, ob->class, mb, (u8*)jargs));
976 jobject Jam_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz,
977 jmethodID methodID, ...) {
978 Object *ret;
979 va_list jargs;
980 va_start(jargs, methodID);
981 ret = addJNILref(*(Object**) executeMethodVaList((Object*)obj,
982 (Class*)clazz, (MethodBlock*)methodID, jargs));
983 va_end(jargs);
984 return (jobject)ret;
987 jobject Jam_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz,
988 jmethodID methodID, va_list jargs) {
989 return (jobject)addJNILref(*(Object**) executeMethodVaList((Object*)obj,
990 (Class*)clazz, (MethodBlock*)methodID, jargs));
993 jobject Jam_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz,
994 jmethodID methodID, jvalue *jargs) {
995 return (jobject)addJNILref(*(Object**) executeMethodList((Object*)obj,
996 (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs));
999 jobject Jam_CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
1000 Object *ret;
1001 va_list jargs;
1002 va_start(jargs, methodID);
1003 ret = addJNILref(*(Object**) executeMethodVaList(NULL,
1004 (Class*)clazz, (MethodBlock*)methodID, jargs));
1005 va_end(jargs);
1006 return (jobject)ret;
1009 jobject Jam_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
1010 jmethodID methodID, va_list jargs) {
1011 return (jobject)addJNILref(*(Object**) executeMethodVaList(NULL,
1012 (Class*)clazz, (MethodBlock*)methodID, jargs));
1015 jobject Jam_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
1016 jmethodID methodID, jvalue *jargs) {
1017 return (jobject)addJNILref(*(Object**) executeMethodList(NULL,
1018 (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs));
1021 void Jam_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
1022 va_list jargs;
1023 MethodBlock *mb;
1024 Object *ob = (Object *)obj;
1026 va_start(jargs, methodID);
1027 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1028 executeMethodVaList(ob, ob->class, mb, jargs);
1029 va_end(jargs);
1032 void Jam_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list jargs) {
1033 MethodBlock *mb;
1034 Object *ob = (Object *)obj;
1035 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1036 executeMethodVaList(ob, ob->class, mb, jargs);
1039 void Jam_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *jargs) {
1040 MethodBlock *mb;
1041 Object *ob = (Object *)obj;
1042 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1043 executeMethodList(ob, ob->class, mb, (u8*)jargs);
1046 void Jam_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) {
1047 va_list jargs;
1048 va_start(jargs, methodID);
1049 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs);
1050 va_end(jargs);
1053 void Jam_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
1054 jmethodID methodID, va_list jargs) {
1055 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs);
1058 void Jam_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
1059 jmethodID methodID, jvalue *jargs) {
1060 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs);
1063 void Jam_CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
1064 va_list jargs;
1065 va_start(jargs, methodID);
1066 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);
1067 va_end(jargs);
1070 void Jam_CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list jargs) {
1071 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);
1074 void Jam_CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *jargs) {
1075 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs);
1078 #define NEW_PRIM_ARRAY(type, native_type, array_type) \
1079 native_type##Array Jam_New##type##Array(JNIEnv *env, jsize length) { \
1080 return (native_type##Array) addJNILref(allocTypeArray(array_type, length)); \
1083 #define GET_PRIM_ARRAY_ELEMENTS(type, native_type) \
1084 native_type *Jam_Get##type##ArrayElements(JNIEnv *env, native_type##Array array, \
1085 jboolean *isCopy) { \
1086 if(isCopy != NULL) \
1087 *isCopy = JNI_FALSE; \
1088 addJNIGref((Object*)array); \
1089 return (native_type*)ARRAY_DATA((Object*)array); \
1092 #define RELEASE_PRIM_ARRAY_ELEMENTS(type, native_type) \
1093 void Jam_Release##type##ArrayElements(JNIEnv *env, native_type##Array array, \
1094 native_type *elems, jint mode) { \
1095 delJNIGref((Object*)array); \
1098 #define GET_PRIM_ARRAY_REGION(type, native_type) \
1099 void Jam_Get##type##ArrayRegion(JNIEnv *env, native_type##Array array, jsize start, \
1100 jsize len, native_type *buf) { \
1101 memcpy(buf, (native_type*)ARRAY_DATA((Object*)array) + start, len * sizeof(native_type)); \
1104 #define SET_PRIM_ARRAY_REGION(type, native_type) \
1105 void Jam_Set##type##ArrayRegion(JNIEnv *env, native_type##Array array, jsize start, jsize len, \
1106 native_type *buf) { \
1107 memcpy((native_type*)ARRAY_DATA((Object*)array) + start, buf, len * sizeof(native_type)); \
1110 #define PRIM_ARRAY_OP(type, native_type, array_type) \
1111 NEW_PRIM_ARRAY(type, native_type, array_type); \
1112 GET_PRIM_ARRAY_ELEMENTS(type, native_type); \
1113 RELEASE_PRIM_ARRAY_ELEMENTS(type, native_type); \
1114 GET_PRIM_ARRAY_REGION(type, native_type); \
1115 SET_PRIM_ARRAY_REGION(type, native_type);
1117 PRIM_ARRAY_OP(Boolean, jboolean, T_BOOLEAN);
1118 PRIM_ARRAY_OP(Byte, jbyte, T_BYTE);
1119 PRIM_ARRAY_OP(Char, jchar, T_CHAR);
1120 PRIM_ARRAY_OP(Short, jshort, T_SHORT);
1121 PRIM_ARRAY_OP(Int, jint, T_INT);
1122 PRIM_ARRAY_OP(Long, jlong, T_LONG);
1123 PRIM_ARRAY_OP(Float, jfloat, T_FLOAT);
1124 PRIM_ARRAY_OP(Double, jdouble, T_DOUBLE);
1126 #define METHOD(type, ret_type) \
1127 Jam_Call##type##ret_type##Method, \
1128 Jam_Call##type##ret_type##MethodV, \
1129 Jam_Call##type##ret_type##MethodA
1131 #define METHODS(type) \
1132 METHOD(type, Object), \
1133 METHOD(type, Boolean), \
1134 METHOD(type, Byte), \
1135 METHOD(type, Char), \
1136 METHOD(type, Short), \
1137 METHOD(type, Int), \
1138 METHOD(type, Long), \
1139 METHOD(type, Float), \
1140 METHOD(type, Double), \
1141 METHOD(type, Void)
1143 #define FIELD(direction, type, field_type) \
1144 Jam_##direction##type##field_type##Field
1146 #define FIELDS2(direction, type) \
1147 FIELD(direction, type, Object), \
1148 FIELD(direction, type, Boolean), \
1149 FIELD(direction, type, Byte), \
1150 FIELD(direction, type, Char), \
1151 FIELD(direction, type, Short), \
1152 FIELD(direction, type, Int), \
1153 FIELD(direction, type, Long), \
1154 FIELD(direction, type, Float), \
1155 FIELD(direction, type, Double)
1157 #define FIELDS(type) \
1158 FIELDS2(Get, type), \
1159 FIELDS2(Set, type)
1161 #define ARRAY(op, el_type, type) \
1162 Jam_##op##el_type##Array##type
1164 #define ARRAY_OPS(op, type) \
1165 ARRAY(op, Boolean, type), \
1166 ARRAY(op, Byte, type), \
1167 ARRAY(op, Char, type), \
1168 ARRAY(op, Short, type), \
1169 ARRAY(op, Int, type), \
1170 ARRAY(op, Long, type), \
1171 ARRAY(op, Float, type), \
1172 ARRAY(op, Double, type)
1174 struct _JNINativeInterface Jam_JNINativeInterface = {
1175 NULL,
1176 NULL,
1177 NULL,
1178 NULL,
1179 Jam_GetVersion,
1180 Jam_DefineClass,
1181 Jam_FindClass,
1182 Jam_FromReflectedMethod,
1183 Jam_FromReflectedField,
1184 Jam_ToReflectedMethod,
1185 Jam_GetSuperClass,
1186 Jam_IsAssignableFrom,
1187 Jam_ToReflectedField,
1188 Jam_Throw,
1189 Jam_ThrowNew,
1190 Jam_ExceptionOccurred,
1191 Jam_ExceptionDescribe,
1192 Jam_ExceptionClear,
1193 Jam_FatalError,
1194 Jam_PushLocalFrame,
1195 Jam_PopLocalFrame,
1196 Jam_NewGlobalRef,
1197 Jam_DeleteGlobalRef,
1198 Jam_DeleteLocalRef,
1199 Jam_IsSameObject,
1200 Jam_NewLocalRef,
1201 Jam_EnsureLocalCapacity,
1202 Jam_AllocObject,
1203 Jam_NewObject,
1204 Jam_NewObjectV,
1205 Jam_NewObjectA,
1206 Jam_GetObjectClass,
1207 Jam_IsInstanceOf,
1208 Jam_GetMethodID,
1209 METHODS(/*virtual*/),
1210 METHODS(Nonvirtual),
1211 Jam_GetFieldID,
1212 FIELDS(/*instance*/),
1213 Jam_GetStaticMethodID,
1214 METHODS(Static),
1215 Jam_GetStaticFieldID,
1216 FIELDS(Static),
1217 Jam_NewString,
1218 Jam_GetStringLength,
1219 Jam_GetStringChars,
1220 Jam_ReleaseStringChars,
1221 Jam_NewStringUTF,
1222 Jam_GetStringUTFLength,
1223 Jam_GetStringUTFChars,
1224 Jam_ReleaseStringUTFChars,
1225 Jam_GetArrayLength,
1226 ARRAY(New, Object,),
1227 ARRAY(Get, Object, Element),
1228 ARRAY(Set, Object, Element),
1229 ARRAY_OPS(New,),
1230 ARRAY_OPS(Get, Elements),
1231 ARRAY_OPS(Release, Elements),
1232 ARRAY_OPS(Get, Region),
1233 ARRAY_OPS(Set, Region),
1234 Jam_RegisterNatives,
1235 Jam_UnregisterNatives,
1236 Jam_MonitorEnter,
1237 Jam_MonitorExit,
1238 Jam_GetJavaVM,
1239 Jam_GetStringRegion,
1240 Jam_GetStringUTFRegion,
1241 Jam_GetPrimitiveArrayCritical,
1242 Jam_ReleasePrimitiveArrayCritical,
1243 Jam_GetStringCritical,
1244 Jam_ReleaseStringCritical,
1245 Jam_NewWeakGlobalRef,
1246 Jam_DeleteWeakGlobalRef,
1247 Jam_ExceptionCheck,
1248 Jam_NewDirectByteBuffer,
1249 Jam_GetDirectBufferAddress,
1250 Jam_GetDirectBufferCapacity
1253 jint Jam_DestroyJavaVM(JavaVM *vm) {
1254 mainThreadWaitToExitVM();
1255 exitVM(0);
1257 return JNI_OK;
1260 static void *env = &Jam_JNINativeInterface;
1262 static jint attachCurrentThread(void **penv, void *args, int is_daemon) {
1263 if(threadSelf() == NULL) {
1264 char *name = NULL;
1265 Object *group = NULL;
1267 if(args != NULL) {
1268 JavaVMAttachArgs *attach_args = (JavaVMAttachArgs*)args;
1269 if((attach_args->version != JNI_VERSION_1_4) && (attach_args->version != JNI_VERSION_1_2))
1270 return JNI_EVERSION;
1272 name = attach_args->name;
1273 group = attach_args->group;
1276 if(attachJNIThread(name, is_daemon, group) == NULL)
1277 return JNI_ERR;
1279 initJNILrefs();
1282 *penv = &env;
1283 return JNI_OK;
1286 jint Jam_AttachCurrentThread(JavaVM *vm, void **penv, void *args) {
1287 return attachCurrentThread(penv, args, FALSE);
1290 jint Jam_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args) {
1291 return attachCurrentThread(penv, args, TRUE);
1294 jint Jam_DetachCurrentThread(JavaVM *vm) {
1295 Thread *thread = threadSelf();
1297 if(thread == NULL)
1298 return JNI_EDETACHED;
1300 detachJNIThread(thread);
1301 return JNI_OK;
1304 jint Jam_GetEnv(JavaVM *vm, void **penv, jint version) {
1305 if((version != JNI_VERSION_1_4) && (version != JNI_VERSION_1_2)
1306 && (version != JNI_VERSION_1_1)) {
1307 *penv = NULL;
1308 return JNI_EVERSION;
1311 if(threadSelf() == NULL) {
1312 *penv = NULL;
1313 return JNI_EDETACHED;
1316 *penv = &env;
1317 return JNI_OK;
1320 struct _JNIInvokeInterface Jam_JNIInvokeInterface = {
1321 NULL,
1322 NULL,
1323 NULL,
1324 Jam_DestroyJavaVM,
1325 Jam_AttachCurrentThread,
1326 Jam_DetachCurrentThread,
1327 Jam_GetEnv,
1328 Jam_AttachCurrentThreadAsDaemon,
1331 jint JNI_GetDefaultJavaVMInitArgs(void *args) {
1332 JavaVMInitArgs *vm_args = (JavaVMInitArgs*) args;
1334 if((vm_args->version != JNI_VERSION_1_4) && (vm_args->version != JNI_VERSION_1_2))
1335 return JNI_EVERSION;
1337 return JNI_OK;
1340 jint parseInitOptions(JavaVMInitArgs *vm_args, InitArgs *args) {
1341 Property props[vm_args->nOptions];
1342 int props_count = 0;
1343 int i;
1345 for(i = 0; i < vm_args->nOptions; i++) {
1346 char *string = vm_args->options[i].optionString;
1348 if(strcmp(string, "vfprintf") == 0)
1349 args->vfprintf = vm_args->options[i].extraInfo;
1351 else if(strcmp(string, "exit") == 0)
1352 args->exit = vm_args->options[i].extraInfo;
1354 else if(strcmp(string, "abort") == 0)
1355 args->abort = vm_args->options[i].extraInfo;
1357 else if(strncmp(string, "-verbose:", 9) == 0) {
1358 char *type = &string[8];
1360 do {
1361 type++;
1363 if(strncmp(type, "class", 5) == 0) {
1364 args->verboseclass = TRUE;
1365 type += 5;
1367 else if(strncmp(type, "gc", 2) == 0) {
1368 args->verbosegc = TRUE;
1369 type += 2;
1371 else if(strncmp(type, "jni", 3) == 0) {
1372 args->verbosedll = TRUE;
1373 type += 3;
1375 } while(*type == ',');
1377 } else if(strcmp(string, "-Xnoasyncgc") == 0)
1378 args->noasyncgc = TRUE;
1380 else if(strncmp(string, "-Xms", 4) == 0) {
1381 args->min_heap = parseMemValue(string + 4);
1382 if(args->min_heap < MIN_HEAP)
1383 goto error;
1385 } else if(strncmp(string, "-Xmx", 4) == 0) {
1386 args->max_heap = parseMemValue(string + 4);
1387 if(args->max_heap < MIN_HEAP)
1388 goto error;
1390 } else if(strncmp(string, "-Xss", 4) == 0) {
1391 args->java_stack = parseMemValue(string + 4);
1392 if(args->java_stack < MIN_STACK)
1393 goto error;
1395 } else if(strncmp(string, "-D", 2) == 0) {
1396 char *pntr, *key = strcpy(sysMalloc(strlen(string+2) + 1), string+2);
1397 for(pntr = key; *pntr && (*pntr != '='); pntr++);
1398 if(pntr == key)
1399 goto error;
1401 *pntr++ = '\0';
1402 props[props_count].key = key;
1403 props[props_count++].value = pntr;
1405 } else if(strncmp(string, "-Xbootclasspath:", 16) == 0) {
1407 args->bootpathopt = '\0';
1408 args->bootpath = string + 16;
1410 } else if(strncmp(string, "-Xbootclasspath/a:", 18) == 0 ||
1411 strncmp(string, "-Xbootclasspath/p:", 18) == 0 ||
1412 strncmp(string, "-Xbootclasspath/c:", 18) == 0 ||
1413 strncmp(string, "-Xbootclasspath/v:", 18) == 0) {
1415 args->bootpathopt = string[16];
1416 args->bootpath = string + 18;
1418 } else if(strcmp(string, "-Xnocompact") == 0) {
1419 args->compact_specified = TRUE;
1420 args->do_compact = FALSE;
1422 } else if(strcmp(string, "-Xcompactalways") == 0) {
1423 args->compact_specified = args->do_compact = TRUE;
1424 #ifdef INLINING
1425 } else if(strcmp(string, "-Xnoinlining") == 0) {
1426 /* Turning inlining off is equivalent to setting
1427 code memory to zero */
1428 args->codemem = 0;
1430 } else if(strncmp(string, "-Xreplication:", 14) == 0) {
1431 char *pntr = string + 14;
1433 if(strcmp(pntr, "none") == 0)
1434 args->replication = INT_MAX;
1435 else
1436 if(strcmp(pntr, "always") == 0)
1437 args->replication = 0;
1438 else
1439 args->replication = strtol(pntr, NULL, 0);
1441 } else if(strncmp(string, "-Xcodemem:", 10) == 0) {
1442 char *pntr = string + 10;
1444 args->codemem = strncmp(pntr, "unlimited", 10) == 0 ?
1445 INT_MAX : parseMemValue(pntr);
1446 #endif
1447 } else if(!vm_args->ignoreUnrecognized)
1448 goto error;
1451 if(args->min_heap > args->max_heap)
1452 goto error;
1454 if((args->props_count = props_count)) {
1455 args->commandline_props = (Property*)sysMalloc(props_count * sizeof(Property));
1456 memcpy(args->commandline_props, &props[0], props_count * sizeof(Property));
1459 return JNI_OK;
1461 error:
1462 return JNI_ERR;
1465 jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args) {
1466 JavaVMInitArgs *vm_args = (JavaVMInitArgs*) args;
1467 InitArgs init_args;
1469 if((vm_args->version != JNI_VERSION_1_4) && (vm_args->version != JNI_VERSION_1_2))
1470 return JNI_EVERSION;
1472 setDefaultInitArgs(&init_args);
1474 if(parseInitOptions(vm_args, &init_args) == JNI_ERR)
1475 return JNI_ERR;
1477 init_args.main_stack_base = nativeStackBase();
1478 initVM(&init_args);
1479 initJNILrefs();
1481 *penv = &env;
1482 *pvm = &invokeIntf;
1484 return JNI_OK;
1487 jint JNI_GetCreatedJavaVMs(JavaVM **buff, jsize buff_len, jsize *num) {
1488 if(buff_len > 0) {
1489 *buff = &invokeIntf;
1490 *num = 1;
1491 return JNI_OK;
1493 return JNI_ERR;
1496 void *getJNIInterface() {
1497 return &Jam_JNINativeInterface;
1499 #endif