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.
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 */
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
;
60 /* Initialise the global references table */
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
) {
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
;
92 JNIFrame
*frame
= ensureJNILrefCapacity(JNI_DEFAULT_LREFS
);
95 frame
->next_ref
= frame
->lrefs
+ frame
->mb
->args_count
;
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
)
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
*));
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
;
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");
132 Object
*addJNILref(Object
*ref
) {
133 ExecEnv
*ee
= getExecEnv();
134 JNIFrame
*frame
= (JNIFrame
*)ee
->last_frame
;
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");
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
++)
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");
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
;
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
) {
209 if(global_ref_deleted
>= LIST_INCR
) {
210 new_size
= global_ref_size
;
211 new_table
= global_ref_table
;
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
];
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
);
235 static void delJNIGref(Object
*ref
) {
236 Thread
*self
= threadSelf();
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
++;
249 unlockVMLock(global_ref_lock
, 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();
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
;
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
,
286 return (jobject
) addJNILref(buff
);
289 static void *Jam_GetDirectBufferAddress(JNIEnv
*env
, jobject buffer
) {
290 Object
*buff
= (Object
*)buffer
;
296 Object
*rawdata
= (Object
*)INST_DATA(buff
)[buffAddr_offset
];
298 return (void*)INST_DATA(rawdata
)[rawdata_offset
];
304 jlong
Jam_GetDirectBufferCapacity(JNIEnv
*env
, jobject buffer
) {
305 Object
*buff
= (Object
*)buffer
;
311 Object
*rawdata
= (Object
*)INST_DATA(buff
)[buffAddr_offset
];
313 return (jlong
)INST_DATA(buff
)[buffCap_offset
];
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
);
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
) {
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
);
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
);
369 StringRegion2Utf8((Object
*)string
, start
, len
, buf
);
372 void *Jam_GetPrimitiveArrayCritical(JNIEnv
*env
, jarray array
, jboolean
*isCopy
) {
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
) {
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
;
440 jint
Jam_ThrowNew(JNIEnv
*env
, jclass clazz
, const char *message
) {
441 signalException(CLASS_CB((Class
*)clazz
)->name
, (char*)message
);
445 jthrowable
Jam_ExceptionOccurred(JNIEnv
*env
) {
446 return (jthrowable
) addJNILref(exceptionOccurred());
449 void Jam_ExceptionDescribe(JNIEnv
*env
) {
453 void Jam_ExceptionClear(JNIEnv
*env
) {
457 void Jam_FatalError(JNIEnv
*env
, const char *message
) {
458 jam_fprintf(stderr
, "JNI - FatalError: %s\n", message
);
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
) {
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
);
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
);
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
);
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
);
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
) {
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
) {
560 return getStringUtf8Len((Object
*)string
);
563 const char *Jam_GetStringUTFChars(JNIEnv
*env
, jstring string
, jboolean
*isCopy
) {
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
);
585 va_start(jargs
, methodID
);
586 executeMethodVaList(ob
, ob
->class, (MethodBlock
*)methodID
, 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];
613 signalException("java/lang/NegativeArraySizeException", NULL
);
617 if(element_name
[0] == '[')
618 strcat(strcpy(ac_name
, "["), element_name
);
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
*));
626 if(initialElement
!= NULL
) {
627 Object
**data
= ARRAY_DATA(array
);
630 *data
++ = (Object
*) initialElement
;
632 return (jarray
) addJNILref(array
);
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
) {
650 jint
Jam_UnregisterNatives(JNIEnv
*env
, jclass clazz
) {
654 jint
Jam_MonitorEnter(JNIEnv
*env
, jobject obj
) {
655 objectLock((Object
*)obj
);
659 jint
Jam_MonitorExit(JNIEnv
*env
, jobject obj
) {
660 objectUnlock((Object
*)obj
);
664 struct _JNIInvokeInterface Jam_JNIInvokeInterface
;
665 JavaVM invokeIntf
= &Jam_JNIInvokeInterface
;
667 jint
Jam_GetJavaVM(JNIEnv
*env
, JavaVM
**vm
) {
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; \
775 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
777 return (native_type)0; \
779 va_start(jargs, mID); \
780 ret = (native_type*) executeMethodVaList(ob, ob->class, mb, jargs); \
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; \
806 MethodBlock *mb = lookupVirtualMethod(ob, (MethodBlock*)mID); \
808 return (native_type)0; \
810 va_start(jargs, mID); \
811 ret = executeMethodVaList(ob, ob->class, mb, 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, ...) { \
837 va_start(jargs, methodID); \
838 ret = (native_type*) \
839 executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, jargs); \
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, ...) { \
863 va_start(jargs, methodID); \
864 ret = executeMethodVaList((Object*)obj, (Class*)clazz, (MethodBlock*)methodID, 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, ...) { \
888 va_start(jargs, methodID); \
889 ret = (native_type*) executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs);\
895 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
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, \
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, ...) { \
913 va_start(jargs, methodID); \
914 ret = executeMethodVaList(NULL, (Class*)clazz, (MethodBlock*)methodID, jargs); \
917 return (native_type)*ret; \
920 native_type Jam_CallStatic##type##MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, \
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, \
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
);
946 jobject
Jam_CallObjectMethod(JNIEnv
*env
, jobject obj
, jmethodID methodID
, ...) {
947 Object
*ob
= (Object
*)obj
;
950 MethodBlock
*mb
= lookupVirtualMethod(ob
, (MethodBlock
*)methodID
);
954 va_start(jargs
, methodID
);
955 ret
= addJNILref(*(Object
**) executeMethodVaList(ob
, ob
->class, mb
, jargs
));
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
, ...) {
980 va_start(jargs
, methodID
);
981 ret
= addJNILref(*(Object
**) executeMethodVaList((Object
*)obj
,
982 (Class
*)clazz
, (MethodBlock
*)methodID
, jargs
));
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
, ...) {
1002 va_start(jargs
, methodID
);
1003 ret
= addJNILref(*(Object
**) executeMethodVaList(NULL
,
1004 (Class
*)clazz
, (MethodBlock
*)methodID
, 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
, ...) {
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
);
1032 void Jam_CallVoidMethodV(JNIEnv
*env
, jobject obj
, jmethodID methodID
, va_list jargs
) {
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
) {
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
, ...) {
1048 va_start(jargs
, methodID
);
1049 executeMethodVaList((Object
*)obj
, (Class
*)clazz
, (MethodBlock
*)methodID
, 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
, ...) {
1065 va_start(jargs
, methodID
);
1066 executeMethodVaList(NULL
, (Class
*)clazz
, (MethodBlock
*)methodID
, 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), \
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), \
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
= {
1182 Jam_FromReflectedMethod
,
1183 Jam_FromReflectedField
,
1184 Jam_ToReflectedMethod
,
1186 Jam_IsAssignableFrom
,
1187 Jam_ToReflectedField
,
1190 Jam_ExceptionOccurred
,
1191 Jam_ExceptionDescribe
,
1197 Jam_DeleteGlobalRef
,
1201 Jam_EnsureLocalCapacity
,
1209 METHODS(/*virtual*/),
1210 METHODS(Nonvirtual
),
1212 FIELDS(/*instance*/),
1213 Jam_GetStaticMethodID
,
1215 Jam_GetStaticFieldID
,
1218 Jam_GetStringLength
,
1220 Jam_ReleaseStringChars
,
1222 Jam_GetStringUTFLength
,
1223 Jam_GetStringUTFChars
,
1224 Jam_ReleaseStringUTFChars
,
1226 ARRAY(New
, Object
,),
1227 ARRAY(Get
, Object
, Element
),
1228 ARRAY(Set
, Object
, Element
),
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
,
1239 Jam_GetStringRegion
,
1240 Jam_GetStringUTFRegion
,
1241 Jam_GetPrimitiveArrayCritical
,
1242 Jam_ReleasePrimitiveArrayCritical
,
1243 Jam_GetStringCritical
,
1244 Jam_ReleaseStringCritical
,
1245 Jam_NewWeakGlobalRef
,
1246 Jam_DeleteWeakGlobalRef
,
1248 Jam_NewDirectByteBuffer
,
1249 Jam_GetDirectBufferAddress
,
1250 Jam_GetDirectBufferCapacity
1253 jint
Jam_DestroyJavaVM(JavaVM
*vm
) {
1254 mainThreadWaitToExitVM();
1260 static void *env
= &Jam_JNINativeInterface
;
1262 static jint
attachCurrentThread(void **penv
, void *args
, int is_daemon
) {
1263 if(threadSelf() == NULL
) {
1265 Object
*group
= 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
)
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();
1298 return JNI_EDETACHED
;
1300 detachJNIThread(thread
);
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
)) {
1308 return JNI_EVERSION
;
1311 if(threadSelf() == NULL
) {
1313 return JNI_EDETACHED
;
1320 struct _JNIInvokeInterface Jam_JNIInvokeInterface
= {
1325 Jam_AttachCurrentThread
,
1326 Jam_DetachCurrentThread
,
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
;
1340 jint
parseInitOptions(JavaVMInitArgs
*vm_args
, InitArgs
*args
) {
1341 Property props
[vm_args
->nOptions
];
1342 int props_count
= 0;
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];
1363 if(strncmp(type
, "class", 5) == 0) {
1364 args
->verboseclass
= TRUE
;
1367 else if(strncmp(type
, "gc", 2) == 0) {
1368 args
->verbosegc
= TRUE
;
1371 else if(strncmp(type
, "jni", 3) == 0) {
1372 args
->verbosedll
= TRUE
;
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
)
1385 } else if(strncmp(string
, "-Xmx", 4) == 0) {
1386 args
->max_heap
= parseMemValue(string
+ 4);
1387 if(args
->max_heap
< MIN_HEAP
)
1390 } else if(strncmp(string
, "-Xss", 4) == 0) {
1391 args
->java_stack
= parseMemValue(string
+ 4);
1392 if(args
->java_stack
< MIN_STACK
)
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
++);
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
;
1425 } else if(strcmp(string
, "-Xnoinlining") == 0) {
1426 /* Turning inlining off is equivalent to setting
1427 code memory to zero */
1430 } else if(strncmp(string
, "-Xreplication:", 14) == 0) {
1431 char *pntr
= string
+ 14;
1433 if(strcmp(pntr
, "none") == 0)
1434 args
->replication
= INT_MAX
;
1436 if(strcmp(pntr
, "always") == 0)
1437 args
->replication
= 0;
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
);
1447 } else if(!vm_args
->ignoreUnrecognized
)
1451 if(args
->min_heap
> args
->max_heap
)
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
));
1465 jint
JNI_CreateJavaVM(JavaVM
**pvm
, void **penv
, void *args
) {
1466 JavaVMInitArgs
*vm_args
= (JavaVMInitArgs
*) 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
)
1477 init_args
.main_stack_base
= nativeStackBase();
1487 jint
JNI_GetCreatedJavaVMs(JavaVM
**buff
, jsize buff_len
, jsize
*num
) {
1489 *buff
= &invokeIntf
;
1496 void *getJNIInterface() {
1497 return &Jam_JNINativeInterface
;