jamvm
view src/jni.c @ 403:907df5a02819
Fix storage of protection domain for OpenJDK.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* src/class.c,
* src/jam.h:
Change signature of defineClass to include
protection domain.
* src/jni.c: Fix call to defineClass to send
NULL protection domain as HotSpot does.
* src/natives.c: Send protection domain directly
to defineClass on OpenJDK as there is no field to
inject it into.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* src/class.c,
* src/jam.h:
Change signature of defineClass to include
protection domain.
* src/jni.c: Fix call to defineClass to send
NULL protection domain as HotSpot does.
* src/natives.c: Send protection domain directly
to defineClass on OpenJDK as there is no field to
inject it into.
| author | andrew |
|---|---|
| date | Tue Aug 05 06:03:08 2008 +0100 (2008-08-05) |
| parents | 9709f25628d3 |
| children | 99039a39df1f |
line source
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3 * Robert Lougher <rob@lougher.org.uk>.
4 *
5 * This file is part of JamVM.
6 *
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.
11 *
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.
16 *
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.
20 */
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"
29 #include "symbol.h"
30 #include "excep.h"
32 #define JNI_VERSION JNI_VERSION_1_4
34 /* The extra used in expanding the local refs table.
35 * This must be >= size of JNIFrame to be thread safe
36 * wrt GC thread suspension */
37 #define LIST_INCR 8
39 /* The amount of local reference space "ensured" before
40 entering a JNI method. The method is garaunteed to
41 be able to create this amount without failure */
42 #define JNI_DEFAULT_LREFS 16
44 /* Forward declarations */
45 const jchar *Jam_GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);
46 void Jam_ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars);
47 jobject Jam_NewGlobalRef(JNIEnv *env, jobject obj);
48 void Jam_DeleteGlobalRef(JNIEnv *env, jobject obj);
49 JNIFrame *ensureJNILrefCapacity(int cap);
50 static void initJNIGrefs();
52 /* Cached values initialised on startup for JNI 1.4 NIO support */
53 static int buffCap_offset, buffAddr_offset, rawdata_offset;
54 static Class *buffImpl_class, *rawdata_class;
55 static MethodBlock *buffImpl_init_mb;
56 static char nio_init_OK = FALSE;
58 void initialiseJNI() {
59 FieldBlock *buffCap_fb, *buffAddr_fb, *rawdata_fb;
60 Class *buffer_class = NULL;
62 /* Initialise the global references table */
63 initJNIGrefs();
65 /* Cache class and method/fields for JNI 1.4 NIO support */
67 buffer_class = findSystemClass0(SYMBOL(java_nio_Buffer));
68 buffImpl_class = findSystemClass0(SYMBOL(java_nio_DirectByteBufferImpl_ReadWrite));
69 rawdata_class = findSystemClass0(sizeof(uintptr_t) == 4 ? SYMBOL(gnu_classpath_Pointer32)
70 : SYMBOL(gnu_classpath_Pointer64));
72 if(buffer_class != NULL && buffImpl_class != NULL && rawdata_class != NULL) {
73 buffImpl_init_mb = findMethod(buffImpl_class, SYMBOL(object_init),
74 SYMBOL(_java_lang_Object_gnu_classpath_Pointer_III__V));
76 buffCap_fb = findField(buffer_class, SYMBOL(cap), SYMBOL(I));
77 rawdata_fb = findField(rawdata_class, SYMBOL(data), sizeof(uintptr_t) == 4 ? SYMBOL(I)
78 : SYMBOL(J));
79 buffAddr_fb = findField(buffer_class, SYMBOL(address), SYMBOL(sig_gnu_classpath_Pointer));
80 }
82 if(buffImpl_init_mb == NULL || buffCap_fb == NULL ||
83 rawdata_fb == NULL || buffAddr_fb == NULL) {
84 return;
85 }
87 registerStaticClassRef(&buffImpl_class);
88 registerStaticClassRef(&rawdata_class);
90 buffCap_offset = buffCap_fb->offset;
91 buffAddr_offset = buffAddr_fb->offset;
92 rawdata_offset = rawdata_fb->offset;
93 nio_init_OK = TRUE;
94 }
96 int initJNILrefs() {
97 JNIFrame *frame = ensureJNILrefCapacity(JNI_DEFAULT_LREFS);
99 if(frame != NULL) {
100 frame->next_ref = frame->lrefs + frame->mb->args_count;
101 return TRUE;
102 }
104 return FALSE;
105 }
107 JNIFrame *expandJNILrefs(ExecEnv *ee, JNIFrame *frame, int incr) {
108 JNIFrame *new_frame = (JNIFrame*)((Object**)frame + incr);
110 if((char*)(new_frame + 1) > ee->stack_end)
111 return NULL;
113 memcpy(new_frame, frame, sizeof(JNIFrame));
114 new_frame->ostack = (uintptr_t*)(new_frame + 1);
115 ee->last_frame = (Frame*)new_frame;
116 memset(frame, 0, incr * sizeof(Object*));
117 return new_frame;
118 }
120 JNIFrame *ensureJNILrefCapacity(int cap) {
121 ExecEnv *ee = getExecEnv();
122 JNIFrame *frame = (JNIFrame*)ee->last_frame;
123 int size = (Object**)frame - frame->lrefs - frame->mb->args_count;
125 if(size < cap) {
126 int incr = cap-size;
127 if(incr < sizeof(JNIFrame)/sizeof(Object*))
128 incr = sizeof(JNIFrame)/sizeof(Object*);
130 if((frame = expandJNILrefs(ee, frame, incr)) == NULL)
131 signalException(java_lang_OutOfMemoryError, "JNI local references");
132 }
134 return frame;
135 }
137 Object *addJNILref(Object *ref) {
138 ExecEnv *ee = getExecEnv();
139 JNIFrame *frame = (JNIFrame*)ee->last_frame;
141 if(ref == NULL)
142 return NULL;
144 if(frame->next_ref == (Object**)frame)
145 if((frame = expandJNILrefs(ee, frame, LIST_INCR)) == NULL) {
146 jam_fprintf(stderr, "JNI - FatalError: cannot expand local references.\n");
147 exitVM(1);
148 }
150 return *frame->next_ref++ = ref;
151 }
153 void delJNILref(Object *ref) {
154 ExecEnv *ee = getExecEnv();
155 JNIFrame *frame = (JNIFrame*)ee->last_frame;
156 Object **opntr = frame->lrefs;
158 for(; opntr < frame->next_ref; opntr++)
159 if(*opntr == ref) {
160 *opntr = NULL;
161 return;
162 }
163 }
165 JNIFrame *pushJNILrefFrame(int cap) {
166 ExecEnv *ee = getExecEnv();
167 JNIFrame *frame = (JNIFrame*)ee->last_frame;
168 JNIFrame *new_frame = (JNIFrame*)((Object**)(frame + 1) + cap);
170 if((char*)(new_frame + 1) > ee->stack_end) {
171 signalException(java_lang_OutOfMemoryError, "JNI local references");
172 return NULL;
173 }
175 new_frame->lrefs = new_frame->next_ref = (Object**)(frame + 1);
176 new_frame->ostack = (uintptr_t*)(new_frame + 1);
177 new_frame->prev = frame->prev;
178 new_frame->mb = frame->mb;
180 memset(frame + 1, 0, cap * sizeof(Object*));
181 ee->last_frame = (Frame*)new_frame;
183 return new_frame;
184 }
186 void popJNILrefFrame() {
187 ExecEnv *ee = getExecEnv();
188 JNIFrame *frame = (JNIFrame*)ee->last_frame;
189 JNIFrame *prev = (JNIFrame*)frame->lrefs - 1;
191 ee->last_frame = (Frame*)prev;
192 }
194 static VMLock global_ref_lock;
195 static Object **global_ref_table;
196 static int global_ref_size = 0;
197 static int global_ref_next = 0;
198 static int global_ref_deleted = 0;
200 static void initJNIGrefs() {
201 initVMLock(global_ref_lock);
202 }
204 static Object *addJNIGref(Object *ref) {
205 Thread *self = threadSelf();
206 disableSuspend(self);
207 lockVMLock(global_ref_lock, self);
209 if(global_ref_next == global_ref_size) {
210 int new_size;
211 Object **new_table;
212 int i, j;
214 if(global_ref_deleted >= LIST_INCR) {
215 new_size = global_ref_size;
216 new_table = global_ref_table;
217 } else {
218 new_size = global_ref_size + LIST_INCR - global_ref_deleted;
219 new_table = (Object**)sysMalloc(new_size * sizeof(Object*));
220 }
222 for(i = 0, j = 0; i < global_ref_size; i++)
223 if(global_ref_table[i])
224 new_table[j++] = global_ref_table[i];
226 global_ref_next = j;
227 global_ref_size = new_size;
228 global_ref_table = new_table;
229 global_ref_deleted = 0;
230 }
232 global_ref_table[global_ref_next++] = ref;
234 unlockVMLock(global_ref_lock, self);
235 enableSuspend(self);
237 return ref;
238 }
240 static void delJNIGref(Object *ref) {
241 Thread *self = threadSelf();
242 int i;
244 disableSuspend(self);
245 lockVMLock(global_ref_lock, self);
247 for(i = 0; i < global_ref_next; i++)
248 if(global_ref_table[i] == ref) {
249 global_ref_table[i] = NULL;
250 global_ref_deleted++;
251 break;
252 }
254 unlockVMLock(global_ref_lock, self);
255 enableSuspend(self);
256 }
258 /* Called during mark phase of GC. Safe from
259 suspension but must grab lock to ensure list
260 isn't being modified by another thread. */
262 void markJNIGlobalRefs() {
263 Thread *self = threadSelf();
264 int i;
266 lockVMLock(global_ref_lock, self);
268 for(i = 0; i < global_ref_next; i++)
269 if(global_ref_table[i])
270 markConservativeRoot(global_ref_table[i]);
272 unlockVMLock(global_ref_lock, self);
273 }
275 /* Extensions added to JNI in JDK 1.4 */
277 jobject Jam_NewDirectByteBuffer(JNIEnv *env, void *addr, jlong capacity) {
278 Object *buff, *rawdata;
280 if(!nio_init_OK)
281 return NULL;
283 if((buff = allocObject(buffImpl_class)) != NULL &&
284 (rawdata = allocObject(rawdata_class)) != NULL) {
286 INST_DATA(rawdata)[rawdata_offset] = (uintptr_t)addr;
287 executeMethod(buff, buffImpl_init_mb, NULL, rawdata, (int)capacity,
288 (int)capacity, 0);
289 }
291 return (jobject) addJNILref(buff);
292 }
294 static void *Jam_GetDirectBufferAddress(JNIEnv *env, jobject buffer) {
295 Object *buff = (Object*)buffer;
297 if(!nio_init_OK)
298 return NULL;
300 if(buff != NULL) {
301 Object *rawdata = (Object *)INST_DATA(buff)[buffAddr_offset];
302 if(rawdata != NULL)
303 return (void*)INST_DATA(rawdata)[rawdata_offset];
304 }
306 return NULL;
307 }
309 jlong Jam_GetDirectBufferCapacity(JNIEnv *env, jobject buffer) {
310 Object *buff = (Object*)buffer;
312 if(!nio_init_OK)
313 return -1;
315 if(buff != NULL) {
316 Object *rawdata = (Object *)INST_DATA(buff)[buffAddr_offset];
317 if(rawdata != NULL)
318 return (jlong)INST_DATA(buff)[buffCap_offset];
319 }
321 return -1;
322 }
324 /* Extensions added to JNI in JDK 1.2 */
326 jmethodID Jam_FromReflectedMethod(JNIEnv *env, jobject method) {
327 return mbFromReflectObject((Object*)method);
328 }
330 jfieldID Jam_FromReflectedField(JNIEnv *env, jobject field) {
331 return fbFromReflectObject((Object*)field);
332 }
334 jobject Jam_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic) {
335 MethodBlock *mb = (MethodBlock *)methodID;
336 if(mb->name == SYMBOL(object_init))
337 return (jobject) createReflectConstructorObject(mb);
338 else
339 return (jobject) createReflectMethodObject(mb);
340 }
342 jobject Jam_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic) {
343 return (jobject) createReflectFieldObject((FieldBlock *)fieldID);
344 }
346 jint Jam_PushLocalFrame(JNIEnv *env, jint capacity) {
347 return pushJNILrefFrame(capacity) == NULL ? JNI_ERR : JNI_OK;
348 }
350 jobject Jam_PopLocalFrame(JNIEnv *env, jobject result) {
351 popJNILrefFrame();
352 return addJNILref(result);
353 }
355 jobject Jam_NewLocalRef(JNIEnv *env, jobject obj) {
356 return addJNILref(obj);
357 }
359 jint Jam_EnsureLocalCapacity(JNIEnv *env, jint capacity) {
360 return ensureJNILrefCapacity(capacity) == NULL ? JNI_ERR : JNI_OK;
361 }
363 void Jam_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf) {
364 if((start + len) > getStringLen((Object*)string))
365 signalException(java_lang_StringIndexOutOfBoundsException, NULL);
366 else
367 memcpy(buf, getStringChars((Object*)string) + start, len * sizeof(short));
368 }
370 void Jam_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf) {
371 if((start + len) > getStringLen((Object*)string))
372 signalException(java_lang_StringIndexOutOfBoundsException, NULL);
373 else
374 StringRegion2Utf8((Object*)string, start, len, buf);
375 }
377 void *Jam_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) {
378 if(isCopy != NULL)
379 *isCopy = JNI_FALSE;
380 addJNIGref((Object*)array);
381 return ARRAY_DATA((Object*)array);
382 }
384 void Jam_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode) {
385 delJNIGref((Object*)array);
386 }
388 const jchar *Jam_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) {
389 return Jam_GetStringChars(env, string, isCopy);
390 }
392 void Jam_ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *chars) {
393 Jam_ReleaseStringChars(env, string, chars);
394 }
396 jweak Jam_NewWeakGlobalRef(JNIEnv *env, jobject obj) {
397 return Jam_NewGlobalRef(env, obj);
398 }
400 void Jam_DeleteWeakGlobalRef(JNIEnv *env, jweak obj) {
401 Jam_DeleteGlobalRef(env, obj);
402 }
404 jboolean Jam_ExceptionCheck(JNIEnv *env) {
405 return exceptionOccurred() ? JNI_TRUE : JNI_FALSE;
406 }
408 /* JNI 1.1 interface */
410 jint Jam_GetVersion(JNIEnv *env) {
411 return JNI_VERSION;
412 }
414 jclass Jam_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen) {
415 return (jclass)defineClass((char*)name, (char *)buf, 0, (int)bufLen, (Object *)loader, NULL);
416 }
418 jclass Jam_FindClass(JNIEnv *env, const char *name) {
419 /* We use the class loader associated with the calling native method.
420 However, if this has been called from an attached thread there may
421 be no native Java frame. In this case use the system class loader */
422 Frame *last = getExecEnv()->last_frame;
423 Object *loader;
425 if(last->prev) {
426 ClassBlock *cb = CLASS_CB(last->mb->class);
427 loader = cb->class_loader;
429 /* Ensure correct context if called from JNI_OnLoad */
430 if(loader == NULL && cb->name == SYMBOL(java_lang_VMRuntime))
431 loader = (Object*)last->lvars[1];
432 } else
433 loader = getSystemClassLoader();
435 return (jclass) findClassFromClassLoader((char*) name, loader);
436 }
438 jclass Jam_GetSuperClass(JNIEnv *env, jclass clazz) {
439 ClassBlock *cb = CLASS_CB((Class *)clazz);
440 return IS_INTERFACE(cb) ? NULL : (jclass)cb->super;
441 }
443 jboolean Jam_IsAssignableFrom(JNIEnv *env, jclass clazz1, jclass clazz2) {
444 return isInstanceOf((Class*)clazz2, (Class*)clazz1);
445 }
447 jint Jam_Throw(JNIEnv *env, jthrowable obj) {
448 Object *ob = (Object*)obj;
449 setException(ob);
450 return JNI_TRUE;
451 }
453 jint Jam_ThrowNew(JNIEnv *env, jclass clazz, const char *message) {
454 signalExceptionClass((Class*)clazz, (char*)message);
455 return JNI_TRUE;
456 }
458 jthrowable Jam_ExceptionOccurred(JNIEnv *env) {
459 return (jthrowable) addJNILref(exceptionOccurred());
460 }
462 void Jam_ExceptionDescribe(JNIEnv *env) {
463 printException();
464 }
466 void Jam_ExceptionClear(JNIEnv *env) {
467 clearException();
468 }
470 void Jam_FatalError(JNIEnv *env, const char *message) {
471 jam_fprintf(stderr, "JNI - FatalError: %s\n", message);
472 exitVM(1);
473 }
475 jobject Jam_NewGlobalRef(JNIEnv *env, jobject obj) {
476 return addJNIGref((Object*)obj);
477 }
479 void Jam_DeleteGlobalRef(JNIEnv *env, jobject obj) {
480 delJNIGref((Object*)obj);
481 }
483 void Jam_DeleteLocalRef(JNIEnv *env, jobject obj) {
484 delJNILref((Object*)obj);
485 }
487 jboolean Jam_IsSameObject(JNIEnv *env, jobject obj1, jobject obj2) {
488 return obj1 == obj2;
489 }
491 /* JNI helper function. The class may be invalid
492 or it may not have been initialised yet */
493 Object *allocObjectClassCheck(Class *class) {
494 ClassBlock *cb = CLASS_CB(class);
496 /* Check the class can be instantiated */
497 if(cb->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) {
498 signalException(java_lang_InstantiationError, cb->name);
499 return NULL;
500 }
502 /* Creating an instance of a class is an active use;
503 make sure it is initialised */
504 if(initClass(class) == NULL)
505 return NULL;
507 return allocObject(class);
508 }
510 jobject Jam_AllocObject(JNIEnv *env, jclass clazz) {
511 return (jobject) addJNILref(allocObjectClassCheck((Class*)clazz));
512 }
514 jclass Jam_GetObjectClass(JNIEnv *env, jobject obj) {
515 return (jobject)((Object*)obj)->class;
516 }
518 jboolean Jam_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) {
519 return (obj == NULL) || isInstanceOf((Class*)clazz, ((Object*)obj)->class);
520 }
522 jmethodID getMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig, char is_static) {
523 Class *class = initClass((Class *)clazz);
524 MethodBlock *mb = NULL;
526 if(class != NULL) {
527 if(!IS_PRIMITIVE(CLASS_CB(class))) {
528 char *method_name = findUtf8((char*)name), *method_sig = findUtf8((char*)sig);
530 if(method_name != NULL && method_sig != NULL) {
531 if(method_name == SYMBOL(object_init) ||
532 method_name == SYMBOL(class_init))
533 mb = findMethod(class, method_name, method_sig);
534 else
535 mb = lookupMethod(class, method_name, method_sig);
536 }
537 }
539 if(mb == NULL || ((mb->access_flags & ACC_STATIC) != 0) != is_static)
540 signalException(java_lang_NoSuchMethodError, (char*)name);
541 }
543 return (jmethodID) mb;
544 }
546 jmethodID Jam_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
547 return getMethodID(env, clazz, name, sig, FALSE);
548 }
550 jfieldID Jam_GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
551 char *field_name = findUtf8((char*)name), *field_sig = findUtf8((char*)sig);
552 Class *class = initClass((Class *)clazz);
553 FieldBlock *fb = NULL;
555 if(class != NULL) {
556 if(field_name != NULL && field_sig != NULL)
557 fb = lookupField(class, field_name, field_sig);
559 if(fb == NULL)
560 signalException(java_lang_NoSuchFieldError, field_name);
561 }
563 return (jfieldID) fb;
564 }
566 jmethodID Jam_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
567 return getMethodID(env, clazz, name, sig, TRUE);
568 }
570 jfieldID Jam_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
571 char *field_name = findUtf8((char*)name), *field_sig = findUtf8((char*)sig);
572 Class *class = initClass((Class *)clazz);
573 FieldBlock *fb = NULL;
575 if(class != NULL) {
576 if(field_name != NULL && field_sig != NULL)
577 fb = findField(class, field_name, field_sig);
579 if(fb == NULL)
580 signalException(java_lang_NoSuchFieldError, field_name);
581 }
583 return (jfieldID) fb;
584 }
586 jstring Jam_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) {
587 return (jstring) addJNILref(createStringFromUnicode((unsigned short*)unicodeChars, len));
588 }
590 jsize Jam_GetStringLength(JNIEnv *env, jstring string) {
591 return getStringLen((Object*)string);
592 }
594 const jchar *Jam_GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy) {
595 if(isCopy != NULL)
596 *isCopy = JNI_FALSE;
598 /* Pin the reference */
599 addJNIGref(getStringCharsArray((Object*)string));
601 return (const jchar *)getStringChars((Object*)string);
602 }
604 void Jam_ReleaseStringChars(JNIEnv *env, jstring string, const jchar *chars) {
605 /* Unpin the reference */
606 delJNIGref(getStringCharsArray((Object*)string));
607 }
609 jstring Jam_NewStringUTF(JNIEnv *env, const char *bytes) {
610 return (jstring) addJNILref(createString((char*)bytes));
611 }
613 jsize Jam_GetStringUTFLength(JNIEnv *env, jstring string) {
614 if(string == NULL)
615 return 0;
616 return getStringUtf8Len((Object*)string);
617 }
619 const char *Jam_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) {
620 if(isCopy != NULL)
621 *isCopy = JNI_TRUE;
623 if(string == NULL)
624 return NULL;
625 return (const char*)String2Utf8((Object*)string);
626 }
628 void Jam_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *chars) {
629 sysFree((void*)chars);
630 }
632 jsize Jam_GetArrayLength(JNIEnv *env, jarray array) {
633 return ARRAY_LEN((Object*)array);
634 }
636 jobject Jam_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
637 Object *ob = allocObjectClassCheck((Class*)clazz);
639 if(ob) {
640 va_list jargs;
641 va_start(jargs, methodID);
642 executeMethodVaList(ob, ob->class, (MethodBlock*)methodID, jargs);
643 va_end(jargs);
644 }
646 return (jobject) addJNILref(ob);
647 }
649 jobject Jam_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) {
650 Object *ob = allocObjectClassCheck((Class*)clazz);
652 if(ob) executeMethodList(ob, ob->class, (MethodBlock*)methodID, (u8*)args);
653 return (jobject) addJNILref(ob);
654 }
656 jobject Jam_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) {
657 Object *ob = allocObjectClassCheck((Class*)clazz);
659 if(ob) executeMethodVaList(ob, ob->class, (MethodBlock*)methodID, args);
660 return (jobject) addJNILref(ob);
661 }
663 jarray Jam_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) {
664 char *element_name = CLASS_CB((Class*)elementClass)->name;
665 char ac_name[strlen(element_name) + 4];
666 Class *array_class;
668 if(length < 0) {
669 signalException(java_lang_NegativeArraySizeException, NULL);
670 return NULL;
671 }
673 if(element_name[0] == '[')
674 strcat(strcpy(ac_name, "["), element_name);
675 else
676 strcat(strcat(strcpy(ac_name, "[L"), element_name), ";");
678 array_class = findArrayClassFromClass(ac_name, (Class*)elementClass);
679 if(array_class != NULL) {
680 Object *array = allocArray(array_class, length, sizeof(Object*));
681 if(array != NULL) {
682 if(initialElement != NULL) {
683 Object **data = ARRAY_DATA(array);
685 while(length--)
686 *data++ = (Object*) initialElement;
687 }
688 return (jarray) addJNILref(array);
689 }
690 }
691 return NULL;
692 }
694 jarray Jam_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) {
695 return (jarray) addJNILref(((Object**)ARRAY_DATA((Object*)array))[index]);
696 }
698 void Jam_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value) {
699 ((Object**)ARRAY_DATA((Object*)array))[index] = (Object*)value;
700 }
702 jint Jam_RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods) {
703 return JNI_OK;
704 }
706 jint Jam_UnregisterNatives(JNIEnv *env, jclass clazz) {
707 return JNI_OK;
708 }
710 jint Jam_MonitorEnter(JNIEnv *env, jobject obj) {
711 objectLock((Object*)obj);
712 return JNI_OK;
713 }
715 jint Jam_MonitorExit(JNIEnv *env, jobject obj) {
716 objectUnlock((Object*)obj);
717 return JNI_OK;
718 }
720 struct _JNIInvokeInterface Jam_JNIInvokeInterface;
721 JavaVM invokeIntf = &Jam_JNIInvokeInterface;
723 jint Jam_GetJavaVM(JNIEnv *env, JavaVM **vm) {
724 *vm = &invokeIntf;
725 return JNI_OK;
726 }
728 #define GET_FIELD(type, native_type) \
729 native_type Jam_Get##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID) { \
730 FieldBlock *fb = (FieldBlock *) fieldID; \
731 Object *ob = (Object*) obj; \
732 return *(native_type *)&(INST_DATA(ob)[fb->offset]); \
733 }
735 #define INT_GET_FIELD(type, native_type) \
736 native_type Jam_Get##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID) { \
737 FieldBlock *fb = (FieldBlock *) fieldID; \
738 Object *ob = (Object*) obj; \
739 return (native_type)(INST_DATA(ob)[fb->offset]); \
740 }
742 #define SET_FIELD(type, native_type) \
743 void Jam_Set##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID, native_type value) { \
744 Object *ob = (Object*) obj; \
745 FieldBlock *fb = (FieldBlock *) fieldID; \
746 *(native_type *)&(INST_DATA(ob)[fb->offset]) = value; \
747 }
749 #define INT_SET_FIELD(type, native_type) \
750 void Jam_Set##type##Field(JNIEnv *env, jobject obj, jfieldID fieldID, native_type value) { \
751 Object *ob = (Object*) obj; \
752 FieldBlock *fb = (FieldBlock *) fieldID; \
753 INST_DATA(ob)[fb->offset] = (intptr_t)value; \
754 }
756 #define GET_STATIC_FIELD(type, native_type) \
757 native_type Jam_GetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID) { \
758 FieldBlock *fb = (FieldBlock *) fieldID; \
759 return *(native_type *)&fb->static_value; \
760 }
762 #define INT_GET_STATIC_FIELD(type, native_type) \
763 native_type Jam_GetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID) { \
764 FieldBlock *fb = (FieldBlock *) fieldID; \
765 return (native_type)fb->static_value; \
766 }
768 #define SET_STATIC_FIELD(type, native_type) \
769 void Jam_SetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, \
770 native_type value) { \
771 FieldBlock *fb = (FieldBlock *) fieldID; \
772 *(native_type *)&fb->static_value = value; \
773 }
775 #define INT_SET_STATIC_FIELD(type, native_type) \
776 void Jam_SetStatic##type##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, \
777 native_type value) { \
778 FieldBlock *fb = (FieldBlock *) fieldID; \
779 fb->static_value = (intptr_t)value; \
780 }
782 #define FIELD_ACCESS(type, native_type) \
783 GET_FIELD(type, native_type); \
784 SET_FIELD(type, native_type); \
785 GET_STATIC_FIELD(type, native_type); \
786 SET_STATIC_FIELD(type, native_type);
788 #define INT_FIELD_ACCESS(type, native_type) \
789 INT_GET_FIELD(type, native_type); \
790 INT_SET_FIELD(type, native_type); \
791 INT_GET_STATIC_FIELD(type, native_type); \
792 INT_SET_STATIC_FIELD(type, native_type);
794 INT_FIELD_ACCESS(Boolean, jboolean);
795 INT_FIELD_ACCESS(Byte, jbyte);
796 INT_FIELD_ACCESS(Char, jchar);
797 INT_FIELD_ACCESS(Short, jshort);
798 INT_FIELD_ACCESS(Int, jint);
799 FIELD_ACCESS(Long, jlong);
800 FIELD_ACCESS(Float, jfloat);
801 FIELD_ACCESS(Double, jdouble);
803 jobject Jam_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) {
804 FieldBlock *fb = (FieldBlock *) fieldID;
805 Object *ob = (Object*) obj;
806 return (jobject) addJNILref((Object*)(INST_DATA(ob)[fb->offset]));
807 }
809 void Jam_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) {
810 Object *ob = (Object*) obj;
811 FieldBlock *fb = (FieldBlock *) fieldID;
812 INST_DATA(ob)[fb->offset] = (uintptr_t)value;
813 }
815 jobject Jam_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
816 FieldBlock *fb = (FieldBlock *) fieldID;
817 return (jobject) addJNILref((Object*)fb->static_value);
818 }
820 void Jam_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) {
821 FieldBlock *fb = (FieldBlock *) fieldID;
822 fb->static_value = (uintptr_t)value;
823 }
825 #define VIRTUAL_METHOD(type, native_type) \
826 native_type Jam_Call##type##Method(JNIEnv *env, jobject obj, jmethodID mID, ...) { \
827 Object *ob = (Object *)obj; \
828 native_type *ret; \
829 va_list jargs; \
830 \
831 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
832 if(mb == NULL) \
833 return (native_type)0; \
834 \
835 va_start(jargs, mID); \
836 ret = (native_type*) executeMethodVaList(ob, ob->class, mb, jargs); \
837 va_end(jargs); \
838 \
839 return *ret; \
840 } \
841 \
842 native_type Jam_Call##type##MethodV(JNIEnv *env, jobject obj, jmethodID mID, va_list jargs) { \
843 Object *ob = (Object *)obj; \
844 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
845 return mb == NULL ? (native_type)0 : \
846 *(native_type*)executeMethodVaList(ob, ob->class, mb, jargs); \
847 } \
848 \
849 native_type Jam_Call##type##MethodA(JNIEnv *env, jobject obj, jmethodID mID, jvalue *jargs) { \
850 Object *ob = (Object *)obj; \
851 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
852 return mb == NULL ? (native_type)0 : \
853 *(native_type*)executeMethodList(ob, ob->class, mb, (u8*)jargs); \
854 }
856 #define INT_VIRTUAL_METHOD(type, native_type) \
857 native_type Jam_Call##type##Method(JNIEnv *env, jobject obj, jmethodID mID, ...) { \
858 Object *ob = (Object *)obj; \
859 uintptr_t *ret; \
860 va_list jargs; \
861 \
862 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
863 if(mb == NULL) \
864 return (native_type)0; \
865 \
866 va_start(jargs, mID); \
867 ret = executeMethodVaList(ob, ob->class, mb, jargs); \
868 va_end(jargs); \
869 \
870 return (native_type)*ret; \
871 } \
872 \
873 native_type Jam_Call##type##MethodV(JNIEnv *env, jobject obj, jmethodID mID, va_list jargs) { \
874 Object *ob = (Object *)obj; \
875 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
876 return mb == NULL ? (native_type)0 : \
877 (native_type)*(uintptr_t*)executeMethodVaList(ob, ob->class, mb, jargs); \
878 } \
879 \
880 native_type Jam_Call##type##MethodA(JNIEnv *env, jobject obj, jmethodID mID, jvalue *jargs) { \
881 Object *ob = (Object *)obj; \
882 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
883 return mb == NULL ? (native_type)0 : (native_type)*(uintptr_t*) \
884 executeMethodList(ob, ob->class, mb, (u8*)jargs); \
885 }
887 #define NONVIRTUAL_METHOD(type, native_type) \
888 native_type Jam_CallNonvirtual##type##Method(JNIEnv *env, jobject obj, jclass clazz, \
889 jmethodID methodID, ...) { \
890 native_type *ret; \
891 va_list jargs; \
892 \
893 va_start(jargs, methodID); \
894 ret = (native_type*) \
895 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
896 va_end(jargs); \
897 \
898 return *ret; \
899 } \
900 \
901 native_type Jam_CallNonvirtual##type##MethodV(JNIEnv *env, jobject obj, jclass clazz, \
902 jmethodID methodID, va_list jargs) { \
903 return *(native_type*) \
904 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
905 } \
906 \
907 native_type Jam_CallNonvirtual##type##MethodA(JNIEnv *env, jobject obj, jclass clazz, \
908 jmethodID methodID, jvalue *jargs) { \
909 return *(native_type*) \
910 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
911 }
913 #define INT_NONVIRTUAL_METHOD(type, native_type) \
914 native_type Jam_CallNonvirtual##type##Method(JNIEnv *env, jobject obj, jclass clazz, \
915 jmethodID methodID, ...) { \
916 uintptr_t *ret; \
917 va_list jargs; \
918 \
919 va_start(jargs, methodID); \
920 ret = executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
921 va_end(jargs); \
922 \
923 return (native_type)*ret; \
924 } \
925 \
926 native_type Jam_CallNonvirtual##type##MethodV(JNIEnv *env, jobject obj, jclass clazz, \
927 jmethodID methodID, va_list jargs) { \
928 return (native_type)*(uintptr_t*) \
929 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
930 } \
931 \
932 native_type Jam_CallNonvirtual##type##MethodA(JNIEnv *env, jobject obj, jclass clazz, \
933 jmethodID methodID, jvalue *jargs) { \
934 return (native_type)*(uintptr_t*) \
935 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
936 }
938 #define STATIC_METHOD(type, native_type) \
939 native_type Jam_CallStatic##type##Method(JNIEnv *env, jclass clazz, \
940 jmethodID methodID, ...) { \
941 native_type *ret; \
942 va_list jargs; \
943 \
944 va_start(jargs, methodID); \
945 ret = (native_type*) executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);\
946 va_end(jargs); \
947 \
948 return *ret; \
949 } \
950 \
951 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
952 va_list jargs) { \
953 return *(native_type*) \
954 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
955 } \
956 \
957 native_type Jam_CallStatic##type##MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, \
958 jvalue *jargs) { \
959 return *(native_type*) \
960 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
961 }
963 #define INT_STATIC_METHOD(type, native_type) \
964 native_type Jam_CallStatic##type##Method(JNIEnv *env, jclass clazz, \
965 jmethodID methodID, ...) { \
966 uintptr_t *ret; \
967 va_list jargs; \
968 \
969 va_start(jargs, methodID); \
970 ret = executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
971 va_end(jargs); \
972 \
973 return (native_type)*ret; \
974 } \
975 \
976 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
977 va_list jargs) { \
978 return (native_type) *(uintptr_t*) \
979 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
980 } \
981 \
982 native_type Jam_CallStatic##type##MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, \
983 jvalue *jargs) { \
984 return (native_type)*(uintptr_t*) \
985 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs); \
986 }
988 #define CALL_METHOD(access) \
989 INT_##access##_METHOD(Boolean, jboolean); \
990 INT_##access##_METHOD(Byte, jbyte); \
991 INT_##access##_METHOD(Char, jchar); \
992 INT_##access##_METHOD(Short, jshort); \
993 INT_##access##_METHOD(Int, jint); \
994 access##_METHOD(Long, jlong); \
995 access##_METHOD(Float, jfloat); \
996 access##_METHOD(Double, jdouble);
998 CALL_METHOD(VIRTUAL);
999 CALL_METHOD(NONVIRTUAL);
1000 CALL_METHOD(STATIC);
1002 jobject Jam_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
1003 Object *ob = (Object *)obj;
1004 Object *ret;
1005 va_list jargs;
1006 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
1007 if(mb == NULL)
1008 return NULL;
1010 va_start(jargs, methodID);
1011 ret = addJNILref(*(Object**) executeMethodVaList(ob, ob->class, mb, jargs));
1012 va_end(jargs);
1013 return (jobject)ret;
1014 }
1016 jobject Jam_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list jargs) {
1017 Object *ob = (Object *)obj;
1018 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
1020 return mb == NULL ? NULL : (jobject)addJNILref(*(Object**)
1021 executeMethodVaList(ob, ob->class, mb, jargs));
1022 }
1024 jobject Jam_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *jargs) {
1025 Object *ob = (Object *)obj;
1026 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)methodID);
1028 return mb == NULL ? NULL : (jobject)addJNILref(*(Object**)
1029 executeMethodList(ob, ob->class, mb, (u8*)jargs));
1030 }
1032 jobject Jam_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz,
1033 jmethodID methodID, ...) {
1034 Object *ret;
1035 va_list jargs;
1036 va_start(jargs, methodID);
1037 ret = addJNILref(*(Object**) executeMethodVaList((Object*)obj,
1038 (Class*)clazz, (MethodBlock*)methodID, jargs));
1039 va_end(jargs);
1040 return (jobject)ret;
1041 }
1043 jobject Jam_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz,
1044 jmethodID methodID, va_list jargs) {
1045 return (jobject)addJNILref(*(Object**) executeMethodVaList((Object*)obj,
1046 (Class*)clazz, (MethodBlock*)methodID, jargs));
1047 }
1049 jobject Jam_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz,
1050 jmethodID methodID, jvalue *jargs) {
1051 return (jobject)addJNILref(*(Object**) executeMethodList((Object*)obj,
1052 (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs));
1053 }
1055 jobject Jam_CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
1056 Object *ret;
1057 va_list jargs;
1058 va_start(jargs, methodID);
1059 ret = addJNILref(*(Object**) executeMethodVaList(NULL,
1060 (Class*)clazz, (MethodBlock*)methodID, jargs));
1061 va_end(jargs);
1062 return (jobject)ret;
1063 }
1065 jobject Jam_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
1066 jmethodID methodID, va_list jargs) {
1067 return (jobject)addJNILref(*(Object**) executeMethodVaList(NULL,
1068 (Class*)clazz, (MethodBlock*)methodID, jargs));
1069 }
1071 jobject Jam_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
1072 jmethodID methodID, jvalue *jargs) {
1073 return (jobject)addJNILref(*(Object**) executeMethodList(NULL,
1074 (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs));
1075 }
1077 void Jam_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
1078 va_list jargs;
1079 MethodBlock *mb;
1080 Object *ob = (Object *)obj;
1082 va_start(jargs, methodID);
1083 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1084 executeMethodVaList(ob, ob->class, mb, jargs);
1085 va_end(jargs);
1086 }
1088 void Jam_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list jargs) {
1089 MethodBlock *mb;
1090 Object *ob = (Object *)obj;
1091 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1092 executeMethodVaList(ob, ob->class, mb, jargs);
1093 }
1095 void Jam_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *jargs) {
1096 MethodBlock *mb;
1097 Object *ob = (Object *)obj;
1098 if((mb = lookupVirtualMethod(ob, (MethodBlock*)methodID)) != NULL)
1099 executeMethodList(ob, ob->class, mb, (u8*)jargs);
1100 }
1102 void Jam_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) {
1103 va_list jargs;
1104 va_start(jargs, methodID);
1105 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs);
1106 va_end(jargs);
1107 }
1109 void Jam_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
1110 jmethodID methodID, va_list jargs) {
1111 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs);
1112 }
1114 void Jam_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
1115 jmethodID methodID, jvalue *jargs) {
1116 executeMethodList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs);
1117 }
1119 void Jam_CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
1120 va_list jargs;
1121 va_start(jargs, methodID);
1122 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);
1123 va_end(jargs);
1124 }
1126 void Jam_CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list jargs) {
1127 executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);
1128 }
1130 void Jam_CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *jargs) {
1131 executeMethodList(NULL, (Class*)clazz, (MethodBlock*)methodID, (u8*)jargs);
1132 }
1134 #define NEW_PRIM_ARRAY(type, native_type, array_type) \
1135 native_type##Array Jam_New##type##Array(JNIEnv *env, jsize length) { \
1136 return (native_type##Array) addJNILref(allocTypeArray(array_type, length)); \
1137 }
1139 #define GET_PRIM_ARRAY_ELEMENTS(type, native_type) \
1140 native_type *Jam_Get##type##ArrayElements(JNIEnv *env, native_type##Array array, \
1141 jboolean *isCopy) { \
1142 if(isCopy != NULL) \
1143 *isCopy = JNI_FALSE; \
1144 addJNIGref((Object*)array); \
1145 return (native_type*)ARRAY_DATA((Object*)array); \
1146 }
1148 #define RELEASE_PRIM_ARRAY_ELEMENTS(type, native_type) \
1149 void Jam_Release##type##ArrayElements(JNIEnv *env, native_type##Array array, \
1150 native_type *elems, jint mode) { \
1151 delJNIGref((Object*)array); \
1152 }
1154 #define GET_PRIM_ARRAY_REGION(type, native_type) \
1155 void Jam_Get##type##ArrayRegion(JNIEnv *env, native_type##Array array, jsize start, \
1156 jsize len, native_type *buf) { \
1157 memcpy(buf, (native_type*)ARRAY_DATA((Object*)array) + start, len * sizeof(native_type)); \
1158 }
1160 #define SET_PRIM_ARRAY_REGION(type, native_type) \
1161 void Jam_Set##type##ArrayRegion(JNIEnv *env, native_type##Array array, jsize start, jsize len, \
1162 native_type *buf) { \
1163 memcpy((native_type*)ARRAY_DATA((Object*)array) + start, buf, len * sizeof(native_type)); \
1164 }
1166 #define PRIM_ARRAY_OP(type, native_type, array_type) \
1167 NEW_PRIM_ARRAY(type, native_type, array_type); \
1168 GET_PRIM_ARRAY_ELEMENTS(type, native_type); \
1169 RELEASE_PRIM_ARRAY_ELEMENTS(type, native_type); \
1170 GET_PRIM_ARRAY_REGION(type, native_type); \
1171 SET_PRIM_ARRAY_REGION(type, native_type);
1173 PRIM_ARRAY_OP(Boolean, jboolean, T_BOOLEAN);
1174 PRIM_ARRAY_OP(Byte, jbyte, T_BYTE);
1175 PRIM_ARRAY_OP(Char, jchar, T_CHAR);
1176 PRIM_ARRAY_OP(Short, jshort, T_SHORT);
1177 PRIM_ARRAY_OP(Int, jint, T_INT);
1178 PRIM_ARRAY_OP(Long, jlong, T_LONG);
1179 PRIM_ARRAY_OP(Float, jfloat, T_FLOAT);
1180 PRIM_ARRAY_OP(Double, jdouble, T_DOUBLE);
1182 #define METHOD(type, ret_type) \
1183 Jam_Call##type##ret_type##Method, \
1184 Jam_Call##type##ret_type##MethodV, \
1185 Jam_Call##type##ret_type##MethodA
1187 #define METHODS(type) \
1188 METHOD(type, Object), \
1189 METHOD(type, Boolean), \
1190 METHOD(type, Byte), \
1191 METHOD(type, Char), \
1192 METHOD(type, Short), \
1193 METHOD(type, Int), \
1194 METHOD(type, Long), \
1195 METHOD(type, Float), \
1196 METHOD(type, Double), \
1197 METHOD(type, Void)
1199 #define FIELD(direction, type, field_type) \
1200 Jam_##direction##type##field_type##Field
1202 #define FIELDS2(direction, type) \
1203 FIELD(direction, type, Object), \
1204 FIELD(direction, type, Boolean), \
1205 FIELD(direction, type, Byte), \
1206 FIELD(direction, type, Char), \
1207 FIELD(direction, type, Short), \
1208 FIELD(direction, type, Int), \
1209 FIELD(direction, type, Long), \
1210 FIELD(direction, type, Float), \
1211 FIELD(direction, type, Double)
1213 #define FIELDS(type) \
1214 FIELDS2(Get, type), \
1215 FIELDS2(Set, type)
1217 #define ARRAY(op, el_type, type) \
1218 Jam_##op##el_type##Array##type
1220 #define ARRAY_OPS(op, type) \
1221 ARRAY(op, Boolean, type), \
1222 ARRAY(op, Byte, type), \
1223 ARRAY(op, Char, type), \
1224 ARRAY(op, Short, type), \
1225 ARRAY(op, Int, type), \
1226 ARRAY(op, Long, type), \
1227 ARRAY(op, Float, type), \
1228 ARRAY(op, Double, type)
1230 struct _JNINativeInterface Jam_JNINativeInterface = {
1231 NULL,
1232 NULL,
1233 NULL,
1234 NULL,
1235 Jam_GetVersion,
1236 Jam_DefineClass,
1237 Jam_FindClass,
1238 Jam_FromReflectedMethod,
1239 Jam_FromReflectedField,
1240 Jam_ToReflectedMethod,
1241 Jam_GetSuperClass,
1242 Jam_IsAssignableFrom,
1243 Jam_ToReflectedField,
1244 Jam_Throw,
1245 Jam_ThrowNew,
1246 Jam_ExceptionOccurred,
1247 Jam_ExceptionDescribe,
1248 Jam_ExceptionClear,
1249 Jam_FatalError,
1250 Jam_PushLocalFrame,
1251 Jam_PopLocalFrame,
1252 Jam_NewGlobalRef,
1253 Jam_DeleteGlobalRef,
1254 Jam_DeleteLocalRef,
1255 Jam_IsSameObject,
1256 Jam_NewLocalRef,
1257 Jam_EnsureLocalCapacity,
1258 Jam_AllocObject,
1259 Jam_NewObject,
1260 Jam_NewObjectV,
1261 Jam_NewObjectA,
1262 Jam_GetObjectClass,
1263 Jam_IsInstanceOf,
1264 Jam_GetMethodID,
1265 METHODS(/*virtual*/),
1266 METHODS(Nonvirtual),
1267 Jam_GetFieldID,
1268 FIELDS(/*instance*/),
1269 Jam_GetStaticMethodID,
1270 METHODS(Static),
1271 Jam_GetStaticFieldID,
1272 FIELDS(Static),
1273 Jam_NewString,
1274 Jam_GetStringLength,
1275 Jam_GetStringChars,
1276 Jam_ReleaseStringChars,
1277 Jam_NewStringUTF,
1278 Jam_GetStringUTFLength,
1279 Jam_GetStringUTFChars,
1280 Jam_ReleaseStringUTFChars,
1281 Jam_GetArrayLength,
1282 ARRAY(New, Object,),
1283 ARRAY(Get, Object, Element),
1284 ARRAY(Set, Object, Element),
1285 ARRAY_OPS(New,),
1286 ARRAY_OPS(Get, Elements),
1287 ARRAY_OPS(Release, Elements),
1288 ARRAY_OPS(Get, Region),
1289 ARRAY_OPS(Set, Region),
1290 Jam_RegisterNatives,
1291 Jam_UnregisterNatives,
1292 Jam_MonitorEnter,
1293 Jam_MonitorExit,
1294 Jam_GetJavaVM,
1295 Jam_GetStringRegion,
1296 Jam_GetStringUTFRegion,
1297 Jam_GetPrimitiveArrayCritical,
1298 Jam_ReleasePrimitiveArrayCritical,
1299 Jam_GetStringCritical,
1300 Jam_ReleaseStringCritical,
1301 Jam_NewWeakGlobalRef,
1302 Jam_DeleteWeakGlobalRef,
1303 Jam_ExceptionCheck,
1304 Jam_NewDirectByteBuffer,
1305 Jam_GetDirectBufferAddress,
1306 Jam_GetDirectBufferCapacity
1307 };
1309 jint Jam_DestroyJavaVM(JavaVM *vm) {
1310 mainThreadWaitToExitVM();
1311 exitVM(0);
1313 return JNI_OK;
1314 }
1316 static void *env = &Jam_JNINativeInterface;
1318 static jint attachCurrentThread(void **penv, void *args, int is_daemon) {
1319 if(threadSelf() == NULL) {
1320 char *name = NULL;
1321 Object *group = NULL;
1323 if(args != NULL) {
1324 JavaVMAttachArgs *attach_args = (JavaVMAttachArgs*)args;
1325 if((attach_args->version != JNI_VERSION_1_4) && (attach_args->version != JNI_VERSION_1_2))
1326 return JNI_EVERSION;
1328 name = attach_args->name;
1329 group = attach_args->group;
1330 }
1332 if(attachJNIThread(name, is_daemon, group) == NULL)
1333 return JNI_ERR;
1335 initJNILrefs();
1336 }
1338 *penv = &env;
1339 return JNI_OK;
1340 }
1342 jint Jam_AttachCurrentThread(JavaVM *vm, void **penv, void *args) {
1343 return attachCurrentThread(penv, args, FALSE);
1344 }
1346 jint Jam_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args) {
1347 return attachCurrentThread(penv, args, TRUE);
1348 }
1350 jint Jam_DetachCurrentThread(JavaVM *vm) {
1351 Thread *thread = threadSelf();
1353 if(thread == NULL)
1354 return JNI_EDETACHED;
1356 detachJNIThread(thread);
1357 return JNI_OK;
1358 }
1360 jint Jam_GetEnv(JavaVM *vm, void **penv, jint version) {
1361 if((version != JNI_VERSION_1_4) && (version != JNI_VERSION_1_2)
1362 && (version != JNI_VERSION_1_1)) {
1363 *penv = NULL;
1364 return JNI_EVERSION;
1365 }
1367 if(threadSelf() == NULL) {
1368 *penv = NULL;
1369 return JNI_EDETACHED;
1370 }
1372 *penv = &env;
1373 return JNI_OK;
1374 }
1376 struct _JNIInvokeInterface Jam_JNIInvokeInterface = {
1377 NULL,
1378 NULL,
1379 NULL,
1380 Jam_DestroyJavaVM,
1381 Jam_AttachCurrentThread,
1382 Jam_DetachCurrentThread,
1383 Jam_GetEnv,
1384 Jam_AttachCurrentThreadAsDaemon,
1385 };
1387 jint JNI_GetDefaultJavaVMInitArgs(void *args) {
1388 JavaVMInitArgs *vm_args = (JavaVMInitArgs*) args;
1390 if((vm_args->version != JNI_VERSION_1_4) && (vm_args->version != JNI_VERSION_1_2))
1391 return JNI_EVERSION;
1393 return JNI_OK;
1394 }
1396 jint parseInitOptions(JavaVMInitArgs *vm_args, InitArgs *args) {
1397 Property props[vm_args->nOptions];
1398 int props_count = 0;
1399 int i;
1401 for(i = 0; i < vm_args->nOptions; i++) {
1402 char *string = vm_args->options[i].optionString;
1404 if(strcmp(string, "vfprintf") == 0)
1405 args->vfprintf = vm_args->options[i].extraInfo;
1407 else if(strcmp(string, "exit") == 0)
1408 args->exit = vm_args->options[i].extraInfo;
1410 else if(strcmp(string, "abort") == 0)
1411 args->abort = vm_args->options[i].extraInfo;
1413 else if(strncmp(string, "-verbose:", 9) == 0) {
1414 char *type = &string[8];
1416 do {
1417 type++;
1419 if(strncmp(type, "class", 5) == 0) {
1420 args->verboseclass = TRUE;
1421 type += 5;
1422 }
1423 else if(strncmp(type, "gc", 2) == 0) {
1424 args->verbosegc = TRUE;
1425 type += 2;
1426 }
1427 else if(strncmp(type, "jni", 3) == 0) {
1428 args->verbosedll = TRUE;
1429 type += 3;
1430 }
1431 } while(*type == ',');
1433 } else if(strcmp(string, "-Xnoasyncgc") == 0)
1434 args->noasyncgc = TRUE;
1436 else if(strncmp(string, "-Xms", 4) == 0) {
1437 args->min_heap = parseMemValue(string + 4);
1438 if(args->min_heap < MIN_HEAP)
1439 goto error;
1441 } else if(strncmp(string, "-Xmx", 4) == 0) {
1442 args->max_heap = parseMemValue(string + 4);
1443 if(args->max_heap < MIN_HEAP)
1444 goto error;
1446 } else if(strncmp(string, "-Xss", 4) == 0) {
1447 args->java_stack = parseMemValue(string + 4);
1448 if(args->java_stack < MIN_STACK)
1449 goto error;
1451 } else if(strncmp(string, "-D", 2) == 0) {
1452 char *pntr, *key = strcpy(sysMalloc(strlen(string+2) + 1), string+2);
1453 for(pntr = key; *pntr && (*pntr != '='); pntr++);
1454 if(pntr == key)
1455 goto error;
1457 *pntr++ = '\0';
1458 props[props_count].key = key;
1459 props[props_count++].value = pntr;
1461 } else if(strncmp(string, "-Xbootclasspath:", 16) == 0) {
1463 args->bootpathopt = '\0';
1464 args->bootpath = string + 16;
1466 } else if(strncmp(string, "-Xbootclasspath/a:", 18) == 0 ||
1467 strncmp(string, "-Xbootclasspath/p:", 18) == 0 ||
1468 strncmp(string, "-Xbootclasspath/c:", 18) == 0 ||
1469 strncmp(string, "-Xbootclasspath/v:", 18) == 0) {
1471 args->bootpathopt = string[16];
1472 args->bootpath = string + 18;
1474 } else if(strcmp(string, "-Xnocompact") == 0) {
1475 args->compact_specified = TRUE;
1476 args->do_compact = FALSE;
1478 } else if(strcmp(string, "-Xcompactalways") == 0) {
1479 args->compact_specified = args->do_compact = TRUE;
1480 #ifdef INLINING
1481 } else if(strcmp(string, "-Xnoinlining") == 0) {
1482 /* Turning inlining off is equivalent to setting
1483 code memory to zero */
1484 args->codemem = 0;
1486 } else if(strncmp(string, "-Xreplication:", 14) == 0) {
1487 char *pntr = string + 14;
1489 if(strcmp(pntr, "none") == 0)
1490 args->replication = INT_MAX;
1491 else
1492 if(strcmp(pntr, "always") == 0)
1493 args->replication = 0;
1494 else
1495 args->replication = strtol(pntr, NULL, 0);
1497 } else if(strncmp(string, "-Xcodemem:", 10) == 0) {
1498 char *pntr = string + 10;
1500 args->codemem = strncmp(pntr, "unlimited", 10) == 0 ?
1501 INT_MAX : parseMemValue(pntr);
1502 #endif
1503 } else if(!vm_args->ignoreUnrecognized)
1504 goto error;
1505 }
1507 if(args->min_heap > args->max_heap)
1508 goto error;
1510 if((args->props_count = props_count)) {
1511 args->commandline_props = (Property*)sysMalloc(props_count * sizeof(Property));
1512 memcpy(args->commandline_props, &props[0], props_count * sizeof(Property));
1513 }
1515 return JNI_OK;
1517 error:
1518 return JNI_ERR;
1519 }
1521 jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args) {
1522 JavaVMInitArgs *vm_args = (JavaVMInitArgs*) args;
1523 InitArgs init_args;
1525 if((vm_args->version != JNI_VERSION_1_4) && (vm_args->version != JNI_VERSION_1_2))
1526 return JNI_EVERSION;
1528 setDefaultInitArgs(&init_args);
1530 if(parseInitOptions(vm_args, &init_args) == JNI_ERR)
1531 return JNI_ERR;
1533 init_args.main_stack_base = nativeStackBase();
1534 initVM(&init_args);
1535 initJNILrefs();
1537 *penv = &env;
1538 *pvm = &invokeIntf;
1540 return JNI_OK;
1541 }
1543 jint JNI_GetCreatedJavaVMs(JavaVM **buff, jsize buff_len, jsize *num) {
1544 if(buff_len > 0) {
1545 *buff = &invokeIntf;
1546 *num = 1;
1547 return JNI_OK;
1548 }
1549 return JNI_ERR;
1550 }
1552 void *getJNIInterface() {
1553 return &Jam_JNINativeInterface;
1554 }
1555 #endif
