source: trunk/third/gcc/libjava/jni.cc @ 18474

Revision 18474, 67.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18473, which included commits to RCS files with non-trunk default branches.
Line 
1// jni.cc - JNI implementation, including the jump table.
2
3/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
4
5   This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9details.  */
10
11#include <config.h>
12
13#include <stddef.h>
14#include <string.h>
15
16#include <gcj/cni.h>
17#include <jvm.h>
18#include <java-assert.h>
19#include <jni.h>
20#ifdef ENABLE_JVMPI
21#include <jvmpi.h>
22#endif
23
24#include <java/lang/Class.h>
25#include <java/lang/ClassLoader.h>
26#include <java/lang/Throwable.h>
27#include <java/lang/ArrayIndexOutOfBoundsException.h>
28#include <java/lang/StringIndexOutOfBoundsException.h>
29#include <java/lang/UnsatisfiedLinkError.h>
30#include <java/lang/InstantiationException.h>
31#include <java/lang/NoSuchFieldError.h>
32#include <java/lang/NoSuchMethodError.h>
33#include <java/lang/reflect/Constructor.h>
34#include <java/lang/reflect/Method.h>
35#include <java/lang/reflect/Modifier.h>
36#include <java/lang/OutOfMemoryError.h>
37#include <java/util/IdentityHashMap.h>
38#include <java/lang/Integer.h>
39#include <java/lang/ThreadGroup.h>
40#include <java/lang/Thread.h>
41
42#include <gcj/method.h>
43#include <gcj/field.h>
44
45#include <java-interp.h>
46#include <java-threads.h>
47
48using namespace gcj;
49
50// This enum is used to select different template instantiations in
51// the invocation code.
52enum invocation_type
53{
54  normal,
55  nonvirtual,
56  static_type,
57  constructor
58};
59
60// Forward declarations.
61extern struct JNINativeInterface _Jv_JNIFunctions;
62extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions;
63
64// Number of slots in the default frame.  The VM must allow at least
65// 16.
66#define FRAME_SIZE 32
67
68// Mark value indicating this is an overflow frame.
69#define MARK_NONE    0
70// Mark value indicating this is a user frame.
71#define MARK_USER    1
72// Mark value indicating this is a system frame.
73#define MARK_SYSTEM  2
74
75// This structure is used to keep track of local references.
76struct _Jv_JNI_LocalFrame
77{
78  // This is true if this frame object represents a pushed frame (eg
79  // from PushLocalFrame).
80  int marker :  2;
81
82  // Number of elements in frame.
83  int size   : 30;
84
85  // Next frame in chain.
86  _Jv_JNI_LocalFrame *next;
87
88  // The elements.  These are allocated using the C "struct hack".
89  jobject vec[0];
90};
91
92// This holds a reference count for all local references.
93static java::util::IdentityHashMap *local_ref_table;
94// This holds a reference count for all global references.
95static java::util::IdentityHashMap *global_ref_table;
96
97// The only VM.
98static JavaVM *the_vm;
99
100#ifdef ENABLE_JVMPI
101// The only JVMPI interface description.
102static JVMPI_Interface _Jv_JVMPI_Interface;
103
104static jint
105jvmpiEnableEvent (jint event_type, void *)
106{
107  switch (event_type)
108    {
109    case JVMPI_EVENT_OBJECT_ALLOC:
110      _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
111      break;
112
113    case JVMPI_EVENT_THREAD_START:
114      _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
115      break;
116
117    case JVMPI_EVENT_THREAD_END:
118      _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
119      break;
120
121    default:
122      return JVMPI_NOT_AVAILABLE;
123    }
124
125  return JVMPI_SUCCESS;
126}
127
128static jint
129jvmpiDisableEvent (jint event_type, void *)
130{
131  switch (event_type)
132    {
133    case JVMPI_EVENT_OBJECT_ALLOC:
134      _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
135      break;
136
137    default:
138      return JVMPI_NOT_AVAILABLE;
139    }
140
141  return JVMPI_SUCCESS;
142}
143#endif
144
145
146
147void
148_Jv_JNI_Init (void)
149{
150  local_ref_table = new java::util::IdentityHashMap;
151  global_ref_table = new java::util::IdentityHashMap;
152
153#ifdef ENABLE_JVMPI
154  _Jv_JVMPI_Interface.version = 1;
155  _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
156  _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent;
157  _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC;
158  _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC;
159  _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC;
160#endif
161}
162
163// Tell the GC that a certain pointer is live.
164static void
165mark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
166{
167  JvSynchronize sync (ref_table);
168
169  using namespace java::lang;
170  Integer *refcount = (Integer *) ref_table->get (obj);
171  jint val = (refcount == NULL) ? 0 : refcount->intValue ();
172  // FIXME: what about out of memory error?
173  ref_table->put (obj, new Integer (val + 1));
174}
175
176// Unmark a pointer.
177static void
178unmark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
179{
180  JvSynchronize sync (ref_table);
181
182  using namespace java::lang;
183  Integer *refcount = (Integer *) ref_table->get (obj);
184  JvAssert (refcount);
185  jint val = refcount->intValue () - 1;
186  JvAssert (val >= 0);
187  if (val == 0)
188    ref_table->remove (obj);
189  else
190    // FIXME: what about out of memory error?
191    ref_table->put (obj, new Integer (val));
192}
193
194// "Unwrap" some random non-reference type.  This exists to simplify
195// other template functions.
196template<typename T>
197static T
198unwrap (T val)
199{
200  return val;
201}
202
203// Unwrap a weak reference, if required.
204template<typename T>
205static T *
206unwrap (T *obj)
207{
208  using namespace gnu::gcj::runtime;
209  // We can compare the class directly because JNIWeakRef is `final'.
210  // Doing it this way is much faster.
211  if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
212    return obj;
213  JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
214  return reinterpret_cast<T *> (wr->get ());
215}
216
217
218
219static jobject
220_Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
221{
222  // This seems weird but I think it is correct.
223  obj = unwrap (obj);
224  mark_for_gc (obj, global_ref_table);
225  return obj;
226}
227
228static void
229_Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
230{
231  // This seems weird but I think it is correct.
232  obj = unwrap (obj);
233  unmark_for_gc (obj, global_ref_table);
234}
235
236static void
237_Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
238{
239  _Jv_JNI_LocalFrame *frame;
240
241  // This seems weird but I think it is correct.
242  obj = unwrap (obj);
243
244  for (frame = env->locals; frame != NULL; frame = frame->next)
245    {
246      for (int i = 0; i < frame->size; ++i)
247        {
248          if (frame->vec[i] == obj)
249            {
250              frame->vec[i] = NULL;
251              unmark_for_gc (obj, local_ref_table);
252              return;
253            }
254        }
255
256      // Don't go past a marked frame.
257      JvAssert (frame->marker == MARK_NONE);
258    }
259
260  JvAssert (0);
261}
262
263static jint
264_Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
265{
266  // It is easier to just always allocate a new frame of the requested
267  // size.  This isn't the most efficient thing, but for now we don't
268  // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
269
270  _Jv_JNI_LocalFrame *frame;
271  try
272    {
273      frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
274                                                 + size * sizeof (jobject));
275    }
276  catch (jthrowable t)
277    {
278      env->ex = t;
279      return JNI_ERR;
280    }
281
282  frame->marker = MARK_NONE;
283  frame->size = size;
284  memset (&frame->vec[0], 0, size * sizeof (jobject));
285  frame->next = env->locals;
286  env->locals = frame;
287
288  return 0;
289}
290
291static jint
292_Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
293{
294  jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
295  if (r < 0)
296    return r;
297
298  // The new frame is on top.
299  env->locals->marker = MARK_USER;
300
301  return 0;
302}
303
304static jobject
305_Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
306{
307  // This seems weird but I think it is correct.
308  obj = unwrap (obj);
309
310  // Try to find an open slot somewhere in the topmost frame.
311  _Jv_JNI_LocalFrame *frame = env->locals;
312  bool done = false, set = false;
313  for (; frame != NULL && ! done; frame = frame->next)
314    {
315      for (int i = 0; i < frame->size; ++i)
316        {
317          if (frame->vec[i] == NULL)
318            {
319              set = true;
320              done = true;
321              frame->vec[i] = obj;
322              break;
323            }
324        }
325
326      // If we found a slot, or if the frame we just searched is the
327      // mark frame, then we are done.
328      if (done || frame == NULL || frame->marker != MARK_NONE)
329        break;
330    }
331
332  if (! set)
333    {
334      // No slots, so we allocate a new frame.  According to the spec
335      // we could just die here.  FIXME: return value.
336      _Jv_JNI_EnsureLocalCapacity (env, 16);
337      // We know the first element of the new frame will be ok.
338      env->locals->vec[0] = obj;
339    }
340
341  mark_for_gc (obj, local_ref_table);
342  return obj;
343}
344
345static jobject
346_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
347{
348  _Jv_JNI_LocalFrame *rf = env->locals;
349
350  bool done = false;
351  while (rf != NULL && ! done)
352    {
353      for (int i = 0; i < rf->size; ++i)
354        if (rf->vec[i] != NULL)
355          unmark_for_gc (rf->vec[i], local_ref_table);
356
357      // If the frame we just freed is the marker frame, we are done.
358      done = (rf->marker == stop);
359
360      _Jv_JNI_LocalFrame *n = rf->next;
361      // When N==NULL, we've reached the stack-allocated frame, and we
362      // must not free it.  However, we must be sure to clear all its
363      // elements, since we might conceivably reuse it.
364      if (n == NULL)
365        {
366          memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
367          break;
368        }
369
370      _Jv_Free (rf);
371      rf = n;
372    }
373
374  // Update the local frame information.
375  env->locals = rf;
376
377  return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
378}
379
380static jobject
381_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
382{
383  return _Jv_JNI_PopLocalFrame (env, result, MARK_USER);
384}
385
386// Pop a `system' frame from the stack.  This is `extern "C"' as it is
387// used by the compiler.
388extern "C" void
389_Jv_JNI_PopSystemFrame (JNIEnv *env)
390{
391  _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
392
393  if (env->ex)
394    {
395      jthrowable t = env->ex;
396      env->ex = NULL;
397      throw t;
398    }
399}
400
401// This function is used from other template functions.  It wraps the
402// return value appropriately; we specialize it so that object returns
403// are turned into local references.
404template<typename T>
405static T
406wrap_value (JNIEnv *, T value)
407{
408  return value;
409}
410
411// This specialization is used for jobject, jclass, jstring, jarray,
412// etc.
413template<typename T>
414static T *
415wrap_value (JNIEnv *env, T *value)
416{
417  return (value == NULL
418          ? value
419          : (T *) _Jv_JNI_NewLocalRef (env, (jobject) value));
420}
421
422
423
424static jint
425_Jv_JNI_GetVersion (JNIEnv *)
426{
427  return JNI_VERSION_1_2;
428}
429
430static jclass
431_Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
432                     const jbyte *buf, jsize bufLen)
433{
434  try
435    {
436      loader = unwrap (loader);
437
438      jbyteArray bytes = JvNewByteArray (bufLen);
439
440      jbyte *elts = elements (bytes);
441      memcpy (elts, buf, bufLen * sizeof (jbyte));
442
443      java::lang::ClassLoader *l
444        = reinterpret_cast<java::lang::ClassLoader *> (loader);
445
446      jclass result = l->defineClass (bytes, 0, bufLen);
447      return (jclass) wrap_value (env, result);
448    }
449  catch (jthrowable t)
450    {
451      env->ex = t;
452      return NULL;
453    }
454}
455
456static jclass
457_Jv_JNI_FindClass (JNIEnv *env, const char *name)
458{
459  // FIXME: assume that NAME isn't too long.
460  int len = strlen (name);
461  char s[len + 1];
462  for (int i = 0; i <= len; ++i)
463    s[i] = (name[i] == '/') ? '.' : name[i];
464
465  jclass r = NULL;
466  try
467    {
468      // This might throw an out of memory exception.
469      jstring n = JvNewStringUTF (s);
470
471      java::lang::ClassLoader *loader = NULL;
472      if (env->klass != NULL)
473        loader = env->klass->getClassLoader ();
474
475      if (loader == NULL)
476        {
477          // FIXME: should use getBaseClassLoader, but we don't have that
478          // yet.
479          loader = java::lang::ClassLoader::getSystemClassLoader ();
480        }
481
482      r = loader->loadClass (n);
483    }
484  catch (jthrowable t)
485    {
486      env->ex = t;
487    }
488
489  return (jclass) wrap_value (env, r);
490}
491
492static jclass
493_Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
494{
495  return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
496}
497
498static jboolean
499_Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
500{
501  return unwrap (clazz1)->isAssignableFrom (unwrap (clazz2));
502}
503
504static jint
505_Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
506{
507  // We check in case the user did some funky cast.
508  obj = unwrap (obj);
509  JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
510  env->ex = obj;
511  return 0;
512}
513
514static jint
515_Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
516{
517  using namespace java::lang::reflect;
518
519  clazz = unwrap (clazz);
520  JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
521
522  int r = JNI_OK;
523  try
524    {
525      JArray<jclass> *argtypes
526        = (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
527                                               NULL);
528
529      jclass *elts = elements (argtypes);
530      elts[0] = &StringClass;
531
532      Constructor *cons = clazz->getConstructor (argtypes);
533
534      jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
535      jobject *velts = elements (values);
536      velts[0] = JvNewStringUTF (message);
537
538      jobject obj = cons->newInstance (values);
539
540      env->ex = reinterpret_cast<jthrowable> (obj);
541    }
542  catch (jthrowable t)
543    {
544      env->ex = t;
545      r = JNI_ERR;
546    }
547
548  return r;
549}
550
551static jthrowable
552_Jv_JNI_ExceptionOccurred (JNIEnv *env)
553{
554  return (jthrowable) wrap_value (env, env->ex);
555}
556
557static void
558_Jv_JNI_ExceptionDescribe (JNIEnv *env)
559{
560  if (env->ex != NULL)
561    env->ex->printStackTrace();
562}
563
564static void
565_Jv_JNI_ExceptionClear (JNIEnv *env)
566{
567  env->ex = NULL;
568}
569
570static jboolean
571_Jv_JNI_ExceptionCheck (JNIEnv *env)
572{
573  return env->ex != NULL;
574}
575
576static void
577_Jv_JNI_FatalError (JNIEnv *, const char *message)
578{
579  JvFail (message);
580}
581
582
583
584static jboolean
585_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
586{
587  return unwrap (obj1) == unwrap (obj2);
588}
589
590static jobject
591_Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
592{
593  jobject obj = NULL;
594  using namespace java::lang::reflect;
595
596  try
597    {
598      clazz = unwrap (clazz);
599      JvAssert (clazz && ! clazz->isArray ());
600      if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
601        env->ex = new java::lang::InstantiationException ();
602      else
603        {
604          // FIXME: will this work for String?
605          obj = JvAllocObject (clazz);
606        }
607    }
608  catch (jthrowable t)
609    {
610      env->ex = t;
611    }
612
613  return wrap_value (env, obj);
614}
615
616static jclass
617_Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
618{
619  obj = unwrap (obj);
620  JvAssert (obj);
621  return (jclass) wrap_value (env, obj->getClass());
622}
623
624static jboolean
625_Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
626{
627  return unwrap (clazz)->isInstance(unwrap (obj));
628}
629
630
631
632//
633// This section concerns method invocation.
634//
635
636template<jboolean is_static>
637static jmethodID
638_Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
639                        const char *name, const char *sig)
640{
641  try
642    {
643      clazz = unwrap (clazz);
644      _Jv_InitClass (clazz);
645
646      _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
647
648      // FIXME: assume that SIG isn't too long.
649      int len = strlen (sig);
650      char s[len + 1];
651      for (int i = 0; i <= len; ++i)
652        s[i] = (sig[i] == '/') ? '.' : sig[i];
653      _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1);
654
655      JvAssert (! clazz->isPrimitive());
656
657      using namespace java::lang::reflect;
658
659      while (clazz != NULL)
660        {
661          jint count = JvNumMethods (clazz);
662          jmethodID meth = JvGetFirstMethod (clazz);
663
664          for (jint i = 0; i < count; ++i)
665            {
666              if (((is_static && Modifier::isStatic (meth->accflags))
667                   || (! is_static && ! Modifier::isStatic (meth->accflags)))
668                  && _Jv_equalUtf8Consts (meth->name, name_u)
669                  && _Jv_equalUtf8Consts (meth->signature, sig_u))
670                return meth;
671
672              meth = meth->getNextMethod();
673            }
674
675          clazz = clazz->getSuperclass ();
676        }
677
678      env->ex = new java::lang::NoSuchMethodError ();
679    }
680  catch (jthrowable t)
681    {
682      env->ex = t;
683    }
684
685  return NULL;
686}
687
688// This is a helper function which turns a va_list into an array of
689// `jvalue's.  It needs signature information in order to do its work.
690// The array of values must already be allocated.
691static void
692array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
693{
694  jclass *arg_elts = elements (arg_types);
695  for (int i = 0; i < arg_types->length; ++i)
696    {
697      if (arg_elts[i] == JvPrimClass (byte))
698        values[i].b = (jbyte) va_arg (vargs, int);
699      else if (arg_elts[i] == JvPrimClass (short))
700        values[i].s = (jshort) va_arg (vargs, int);
701      else if (arg_elts[i] == JvPrimClass (int))
702        values[i].i = va_arg (vargs, jint);
703      else if (arg_elts[i] == JvPrimClass (long))
704        values[i].j = va_arg (vargs, jlong);
705      else if (arg_elts[i] == JvPrimClass (float))
706        values[i].f = va_arg (vargs, jfloat);
707      else if (arg_elts[i] == JvPrimClass (double))
708        values[i].d = va_arg (vargs, jdouble);
709      else if (arg_elts[i] == JvPrimClass (boolean))
710        values[i].z = (jboolean) va_arg (vargs, int);
711      else if (arg_elts[i] == JvPrimClass (char))
712        values[i].c = (jchar) va_arg (vargs, int);
713      else
714        {
715          // An object.
716          values[i].l = unwrap (va_arg (vargs, jobject));
717        }
718    }
719}
720
721// This can call any sort of method: virtual, "nonvirtual", static, or
722// constructor.
723template<typename T, invocation_type style>
724static T
725_Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
726                        jmethodID id, va_list vargs)
727{
728  obj = unwrap (obj);
729  klass = unwrap (klass);
730
731  if (style == normal)
732    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
733
734  jclass decl_class = klass ? klass : obj->getClass ();
735  JvAssert (decl_class != NULL);
736
737  jclass return_type;
738  JArray<jclass> *arg_types;
739
740  try
741    {
742      _Jv_GetTypesFromSignature (id, decl_class,
743                                 &arg_types, &return_type);
744
745      jvalue args[arg_types->length];
746      array_from_valist (args, arg_types, vargs);
747
748      // For constructors we need to pass the Class we are instantiating.
749      if (style == constructor)
750        return_type = klass;
751
752      jvalue result;
753      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
754                                          style == constructor,
755                                          arg_types, args, &result);
756
757      if (ex != NULL)
758        env->ex = ex;
759
760      // We cheat a little here.  FIXME.
761      return wrap_value (env, * (T *) &result);
762    }
763  catch (jthrowable t)
764    {
765      env->ex = t;
766    }
767
768  return wrap_value (env, (T) 0);
769}
770
771template<typename T, invocation_type style>
772static T
773_Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
774                       jmethodID method, ...)
775{
776  va_list args;
777  T result;
778
779  va_start (args, method);
780  result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
781  va_end (args);
782
783  return result;
784}
785
786template<typename T, invocation_type style>
787static T
788_Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
789                        jmethodID id, jvalue *args)
790{
791  obj = unwrap (obj);
792  klass = unwrap (klass);
793
794  if (style == normal)
795    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
796
797  jclass decl_class = klass ? klass : obj->getClass ();
798  JvAssert (decl_class != NULL);
799
800  jclass return_type;
801  JArray<jclass> *arg_types;
802  try
803    {
804      _Jv_GetTypesFromSignature (id, decl_class,
805                                 &arg_types, &return_type);
806
807      // For constructors we need to pass the Class we are instantiating.
808      if (style == constructor)
809        return_type = klass;
810
811      // Unwrap arguments as required.  Eww.
812      jclass *type_elts = elements (arg_types);
813      jvalue arg_copy[arg_types->length];
814      for (int i = 0; i < arg_types->length; ++i)
815        {
816          if (type_elts[i]->isPrimitive ())
817            arg_copy[i] = args[i];
818          else
819            arg_copy[i].l = unwrap (args[i].l);
820        }
821
822      jvalue result;
823      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
824                                          style == constructor,
825                                          arg_types, arg_copy, &result);
826
827      if (ex != NULL)
828        env->ex = ex;
829
830      // We cheat a little here.  FIXME.
831      return wrap_value (env, * (T *) &result);
832    }
833  catch (jthrowable t)
834    {
835      env->ex = t;
836    }
837
838  return wrap_value (env, (T) 0);
839}
840
841template<invocation_type style>
842static void
843_Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
844                            jmethodID id, va_list vargs)
845{
846  obj = unwrap (obj);
847  klass = unwrap (klass);
848
849  if (style == normal)
850    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
851
852  jclass decl_class = klass ? klass : obj->getClass ();
853  JvAssert (decl_class != NULL);
854
855  jclass return_type;
856  JArray<jclass> *arg_types;
857  try
858    {
859      _Jv_GetTypesFromSignature (id, decl_class,
860                                 &arg_types, &return_type);
861
862      jvalue args[arg_types->length];
863      array_from_valist (args, arg_types, vargs);
864
865      // For constructors we need to pass the Class we are instantiating.
866      if (style == constructor)
867        return_type = klass;
868
869      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
870                                          style == constructor,
871                                          arg_types, args, NULL);
872
873      if (ex != NULL)
874        env->ex = ex;
875    }
876  catch (jthrowable t)
877    {
878      env->ex = t;
879    }
880}
881
882template<invocation_type style>
883static void
884_Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
885                           jmethodID method, ...)
886{
887  va_list args;
888
889  va_start (args, method);
890  _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
891  va_end (args);
892}
893
894template<invocation_type style>
895static void
896_Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
897                            jmethodID id, jvalue *args)
898{
899  if (style == normal)
900    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
901
902  jclass decl_class = klass ? klass : obj->getClass ();
903  JvAssert (decl_class != NULL);
904
905  jclass return_type;
906  JArray<jclass> *arg_types;
907  try
908    {
909      _Jv_GetTypesFromSignature (id, decl_class,
910                                 &arg_types, &return_type);
911
912      // Unwrap arguments as required.  Eww.
913      jclass *type_elts = elements (arg_types);
914      jvalue arg_copy[arg_types->length];
915      for (int i = 0; i < arg_types->length; ++i)
916        {
917          if (type_elts[i]->isPrimitive ())
918            arg_copy[i] = args[i];
919          else
920            arg_copy[i].l = unwrap (args[i].l);
921        }
922
923      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
924                                          style == constructor,
925                                          arg_types, args, NULL);
926
927      if (ex != NULL)
928        env->ex = ex;
929    }
930  catch (jthrowable t)
931    {
932      env->ex = t;
933    }
934}
935
936// Functions with this signature are used to implement functions in
937// the CallMethod family.
938template<typename T>
939static T
940_Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
941{
942  return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
943}
944
945// Functions with this signature are used to implement functions in
946// the CallMethod family.
947template<typename T>
948static T
949_Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
950{
951  va_list args;
952  T result;
953
954  va_start (args, id);
955  result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
956  va_end (args);
957
958  return result;
959}
960
961// Functions with this signature are used to implement functions in
962// the CallMethod family.
963template<typename T>
964static T
965_Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
966{
967  return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
968}
969
970static void
971_Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
972{
973  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
974}
975
976static void
977_Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
978{
979  va_list args;
980
981  va_start (args, id);
982  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
983  va_end (args);
984}
985
986static void
987_Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
988{
989  _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
990}
991
992// Functions with this signature are used to implement functions in
993// the CallStaticMethod family.
994template<typename T>
995static T
996_Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
997                           jmethodID id, va_list args)
998{
999  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1000  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1001
1002  return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
1003}
1004
1005// Functions with this signature are used to implement functions in
1006// the CallStaticMethod family.
1007template<typename T>
1008static T
1009_Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
1010{
1011  va_list args;
1012  T result;
1013
1014  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1015  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1016
1017  va_start (args, id);
1018  result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
1019                                                   id, args);
1020  va_end (args);
1021
1022  return result;
1023}
1024
1025// Functions with this signature are used to implement functions in
1026// the CallStaticMethod family.
1027template<typename T>
1028static T
1029_Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
1030                           jvalue *args)
1031{
1032  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1033  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1034
1035  return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
1036}
1037
1038static void
1039_Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
1040                               va_list args)
1041{
1042  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1043}
1044
1045static void
1046_Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
1047{
1048  va_list args;
1049
1050  va_start (args, id);
1051  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1052  va_end (args);
1053}
1054
1055static void
1056_Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
1057                               jvalue *args)
1058{
1059  _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
1060}
1061
1062static jobject
1063_Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
1064                    jmethodID id, va_list args)
1065{
1066  JvAssert (klass && ! klass->isArray ());
1067  JvAssert (! strcmp (id->name->data, "<init>")
1068            && id->signature->length > 2
1069            && id->signature->data[0] == '('
1070            && ! strcmp (&id->signature->data[id->signature->length - 2],
1071                         ")V"));
1072
1073  return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1074                                                       id, args);
1075}
1076
1077static jobject
1078_Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
1079{
1080  JvAssert (klass && ! klass->isArray ());
1081  JvAssert (! strcmp (id->name->data, "<init>")
1082            && id->signature->length > 2
1083            && id->signature->data[0] == '('
1084            && ! strcmp (&id->signature->data[id->signature->length - 2],
1085                         ")V"));
1086
1087  va_list args;
1088  jobject result;
1089
1090  va_start (args, id);
1091  result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1092                                                         id, args);
1093  va_end (args);
1094
1095  return result;
1096}
1097
1098static jobject
1099_Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
1100                    jvalue *args)
1101{
1102  JvAssert (klass && ! klass->isArray ());
1103  JvAssert (! strcmp (id->name->data, "<init>")
1104            && id->signature->length > 2
1105            && id->signature->data[0] == '('
1106            && ! strcmp (&id->signature->data[id->signature->length - 2],
1107                         ")V"));
1108
1109  return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
1110                                                       id, args);
1111}
1112
1113
1114
1115template<typename T>
1116static T
1117_Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
1118{
1119  obj = unwrap (obj);
1120  JvAssert (obj);
1121  T *ptr = (T *) ((char *) obj + field->getOffset ());
1122  return wrap_value (env, *ptr);
1123}
1124
1125template<typename T>
1126static void
1127_Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
1128{
1129  obj = unwrap (obj);
1130  value = unwrap (value);
1131
1132  JvAssert (obj);
1133  T *ptr = (T *) ((char *) obj + field->getOffset ());
1134  *ptr = value;
1135}
1136
1137template<jboolean is_static>
1138static jfieldID
1139_Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
1140                       const char *name, const char *sig)
1141{
1142  try
1143    {
1144      clazz = unwrap (clazz);
1145
1146      _Jv_InitClass (clazz);
1147
1148      _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
1149
1150      // FIXME: assume that SIG isn't too long.
1151      int len = strlen (sig);
1152      char s[len + 1];
1153      for (int i = 0; i <= len; ++i)
1154        s[i] = (sig[i] == '/') ? '.' : sig[i];
1155      jclass field_class = _Jv_FindClassFromSignature ((char *) s, NULL);
1156
1157      // FIXME: what if field_class == NULL?
1158
1159      java::lang::ClassLoader *loader = clazz->getClassLoader ();
1160      while (clazz != NULL)
1161        {
1162          // We acquire the class lock so that fields aren't resolved
1163          // while we are running.
1164          JvSynchronize sync (clazz);
1165
1166          jint count = (is_static
1167                        ? JvNumStaticFields (clazz)
1168                        : JvNumInstanceFields (clazz));
1169          jfieldID field = (is_static
1170                            ? JvGetFirstStaticField (clazz)
1171                            : JvGetFirstInstanceField (clazz));
1172          for (jint i = 0; i < count; ++i)
1173            {
1174              _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
1175
1176              // The field might be resolved or it might not be.  It
1177              // is much simpler to always resolve it.
1178              _Jv_ResolveField (field, loader);
1179              if (_Jv_equalUtf8Consts (f_name, a_name)
1180                  && field->getClass() == field_class)
1181                return field;
1182
1183              field = field->getNextField ();
1184            }
1185
1186          clazz = clazz->getSuperclass ();
1187        }
1188
1189      env->ex = new java::lang::NoSuchFieldError ();
1190    }
1191  catch (jthrowable t)
1192    {
1193      env->ex = t;
1194    }
1195  return NULL;
1196}
1197
1198template<typename T>
1199static T
1200_Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
1201{
1202  T *ptr = (T *) field->u.addr;
1203  return wrap_value (env, *ptr);
1204}
1205
1206template<typename T>
1207static void
1208_Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
1209{
1210  value = unwrap (value);
1211  T *ptr = (T *) field->u.addr;
1212  *ptr = value;
1213}
1214
1215static jstring
1216_Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
1217{
1218  try
1219    {
1220      jstring r = _Jv_NewString (unichars, len);
1221      return (jstring) wrap_value (env, r);
1222    }
1223  catch (jthrowable t)
1224    {
1225      env->ex = t;
1226      return NULL;
1227    }
1228}
1229
1230static jsize
1231_Jv_JNI_GetStringLength (JNIEnv *, jstring string)
1232{
1233  return unwrap (string)->length();
1234}
1235
1236static const jchar *
1237_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
1238{
1239  string = unwrap (string);
1240  jchar *result = _Jv_GetStringChars (string);
1241  mark_for_gc (string, global_ref_table);
1242  if (isCopy)
1243    *isCopy = false;
1244  return (const jchar *) result;
1245}
1246
1247static void
1248_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
1249{
1250  unmark_for_gc (unwrap (string), global_ref_table);
1251}
1252
1253static jstring
1254_Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
1255{
1256  try
1257    {
1258      jstring result = JvNewStringUTF (bytes);
1259      return (jstring) wrap_value (env, result);
1260    }
1261  catch (jthrowable t)
1262    {
1263      env->ex = t;
1264      return NULL;
1265    }
1266}
1267
1268static jsize
1269_Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
1270{
1271  return JvGetStringUTFLength (unwrap (string));
1272}
1273
1274static const char *
1275_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy)
1276{
1277  string = unwrap (string);
1278  jsize len = JvGetStringUTFLength (string);
1279  try
1280    {
1281      char *r = (char *) _Jv_Malloc (len + 1);
1282      JvGetStringUTFRegion (string, 0, len, r);
1283      r[len] = '\0';
1284
1285      if (isCopy)
1286        *isCopy = true;
1287
1288      return (const char *) r;
1289    }
1290  catch (jthrowable t)
1291    {
1292      env->ex = t;
1293      return NULL;
1294    }
1295}
1296
1297static void
1298_Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
1299{
1300  _Jv_Free ((void *) utf);
1301}
1302
1303static void
1304_Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
1305                         jchar *buf)
1306{
1307  string = unwrap (string);
1308  jchar *result = _Jv_GetStringChars (string);
1309  if (start < 0 || start > string->length ()
1310      || len < 0 || start + len > string->length ())
1311    {
1312      try
1313        {
1314          env->ex = new java::lang::StringIndexOutOfBoundsException ();
1315        }
1316      catch (jthrowable t)
1317        {
1318          env->ex = t;
1319        }
1320    }
1321  else
1322    memcpy (buf, &result[start], len * sizeof (jchar));
1323}
1324
1325static void
1326_Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
1327                            jsize len, char *buf)
1328{
1329  str = unwrap (str);
1330   
1331  if (start < 0 || start > str->length ()
1332      || len < 0 || start + len > str->length ())
1333    {
1334      try
1335        {
1336          env->ex = new java::lang::StringIndexOutOfBoundsException ();
1337        }
1338      catch (jthrowable t)
1339        {
1340          env->ex = t;
1341        }
1342    }
1343  else
1344    _Jv_GetStringUTFRegion (str, start, len, buf);
1345}
1346
1347static const jchar *
1348_Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
1349{
1350  jchar *result = _Jv_GetStringChars (unwrap (str));
1351  if (isCopy)
1352    *isCopy = false;
1353  return result;
1354}
1355
1356static void
1357_Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1358{
1359  // Nothing.
1360}
1361
1362static jsize
1363_Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1364{
1365  return unwrap (array)->length;
1366}
1367
1368static jarray
1369_Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1370                        jobject init)
1371{
1372  try
1373    {
1374      elementClass = unwrap (elementClass);
1375      init = unwrap (init);
1376
1377      jarray result = JvNewObjectArray (length, elementClass, init);
1378      return (jarray) wrap_value (env, result);
1379    }
1380  catch (jthrowable t)
1381    {
1382      env->ex = t;
1383      return NULL;
1384    }
1385}
1386
1387static jobject
1388_Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1389{
1390  jobject *elts = elements (unwrap (array));
1391  return wrap_value (env, elts[index]);
1392}
1393
1394static void
1395_Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index,
1396                               jobject value)
1397{
1398  try
1399    {
1400      array = unwrap (array);
1401      value = unwrap (value);
1402
1403      _Jv_CheckArrayStore (array, value);
1404      jobject *elts = elements (array);
1405      elts[index] = value;
1406    }
1407  catch (jthrowable t)
1408    {
1409      env->ex = t;
1410    }
1411}
1412
1413template<typename T, jclass K>
1414static JArray<T> *
1415_Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1416{
1417  try
1418    {
1419      return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
1420    }
1421  catch (jthrowable t)
1422    {
1423      env->ex = t;
1424      return NULL;
1425    }
1426}
1427
1428template<typename T>
1429static T *
1430_Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1431                                   jboolean *isCopy)
1432{
1433  array = unwrap (array);
1434  T *elts = elements (array);
1435  if (isCopy)
1436    {
1437      // We elect never to copy.
1438      *isCopy = false;
1439    }
1440  mark_for_gc (array, global_ref_table);
1441  return elts;
1442}
1443
1444template<typename T>
1445static void
1446_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1447                                       T *, jint /* mode */)
1448{
1449  array = unwrap (array);
1450  // Note that we ignore MODE.  We can do this because we never copy
1451  // the array elements.  My reading of the JNI documentation is that
1452  // this is an option for the implementor.
1453  unmark_for_gc (array, global_ref_table);
1454}
1455
1456template<typename T>
1457static void
1458_Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1459                                 jsize start, jsize len,
1460                                 T *buf)
1461{
1462  array = unwrap (array);
1463
1464  // The cast to unsigned lets us save a comparison.
1465  if (start < 0 || len < 0
1466      || (unsigned long) (start + len) > (unsigned long) array->length)
1467    {
1468      try
1469        {
1470          // FIXME: index.
1471          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1472        }
1473      catch (jthrowable t)
1474        {
1475          // Could have thown out of memory error.
1476          env->ex = t;
1477        }
1478    }
1479  else
1480    {
1481      T *elts = elements (array) + start;
1482      memcpy (buf, elts, len * sizeof (T));
1483    }
1484}
1485
1486template<typename T>
1487static void
1488_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1489                                 jsize start, jsize len, T *buf)
1490{
1491  array = unwrap (array);
1492
1493  // The cast to unsigned lets us save a comparison.
1494  if (start < 0 || len < 0
1495      || (unsigned long) (start + len) > (unsigned long) array->length)
1496    {
1497      try
1498        {
1499          // FIXME: index.
1500          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1501        }
1502      catch (jthrowable t)
1503        {
1504          env->ex = t;
1505        }
1506    }
1507  else
1508    {
1509      T *elts = elements (array) + start;
1510      memcpy (elts, buf, len * sizeof (T));
1511    }
1512}
1513
1514static void *
1515_Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1516                                   jboolean *isCopy)
1517{
1518  array = unwrap (array);
1519  // FIXME: does this work?
1520  jclass klass = array->getClass()->getComponentType();
1521  JvAssert (klass->isPrimitive ());
1522  char *r = _Jv_GetArrayElementFromElementType (array, klass);
1523  if (isCopy)
1524    *isCopy = false;
1525  return r;
1526}
1527
1528static void
1529_Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1530{
1531  // Nothing.
1532}
1533
1534static jint
1535_Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj)
1536{
1537  try
1538    {
1539      _Jv_MonitorEnter (unwrap (obj));
1540      return 0;
1541    }
1542  catch (jthrowable t)
1543    {
1544      env->ex = t;
1545    }
1546  return JNI_ERR;
1547}
1548
1549static jint
1550_Jv_JNI_MonitorExit (JNIEnv *env, jobject obj)
1551{
1552  try
1553    {
1554      _Jv_MonitorExit (unwrap (obj));
1555      return 0;
1556    }
1557  catch (jthrowable t)
1558    {
1559      env->ex = t;
1560    }
1561  return JNI_ERR;
1562}
1563
1564// JDK 1.2
1565jobject
1566_Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1567                          jboolean)
1568{
1569  try
1570    {
1571      cls = unwrap (cls);
1572      java::lang::reflect::Field *field = new java::lang::reflect::Field();
1573      field->declaringClass = cls;
1574      field->offset = (char*) fieldID - (char *) cls->fields;
1575      field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1576      return wrap_value (env, field);
1577    }
1578  catch (jthrowable t)
1579    {
1580      env->ex = t;
1581    }
1582  return NULL;
1583}
1584
1585// JDK 1.2
1586static jfieldID
1587_Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1588{
1589  using namespace java::lang::reflect;
1590
1591  f = unwrap (f);
1592  Field *field = reinterpret_cast<Field *> (f);
1593  return _Jv_FromReflectedField (field);
1594}
1595
1596jobject
1597_Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1598                           jboolean)
1599{
1600  using namespace java::lang::reflect;
1601
1602  jobject result = NULL;
1603  klass = unwrap (klass);
1604
1605  try
1606    {
1607      if (_Jv_equalUtf8Consts (id->name, init_name))
1608        {
1609          // A constructor.
1610          Constructor *cons = new Constructor ();
1611          cons->offset = (char *) id - (char *) &klass->methods;
1612          cons->declaringClass = klass;
1613          result = cons;
1614        }
1615      else
1616        {
1617          Method *meth = new Method ();
1618          meth->offset = (char *) id - (char *) &klass->methods;
1619          meth->declaringClass = klass;
1620          result = meth;
1621        }
1622    }
1623  catch (jthrowable t)
1624    {
1625      env->ex = t;
1626    }
1627
1628  return wrap_value (env, result);
1629}
1630
1631static jmethodID
1632_Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1633{
1634  using namespace java::lang::reflect;
1635  method = unwrap (method);
1636  if (Method::class$.isInstance (method))
1637    return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1638  return
1639    _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1640}
1641
1642// JDK 1.2.
1643jweak
1644_Jv_JNI_NewWeakGlobalRef (JNIEnv *env, jobject obj)
1645{
1646  using namespace gnu::gcj::runtime;
1647  JNIWeakRef *ref = NULL;
1648
1649  try
1650    {
1651      // This seems weird but I think it is correct.
1652      obj = unwrap (obj);
1653      ref = new JNIWeakRef (obj);
1654      mark_for_gc (ref, global_ref_table);
1655    }
1656  catch (jthrowable t)
1657    {
1658      env->ex = t;
1659    }
1660
1661  return reinterpret_cast<jweak> (ref);
1662}
1663
1664void
1665_Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
1666{
1667  using namespace gnu::gcj::runtime;
1668  JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
1669  unmark_for_gc (ref, global_ref_table);
1670  ref->clear ();
1671}
1672
1673
1674
1675// Hash table of native methods.
1676static JNINativeMethod *nathash;
1677// Number of slots used.
1678static int nathash_count = 0;
1679// Number of slots available.  Must be power of 2.
1680static int nathash_size = 0;
1681
1682#define DELETED_ENTRY ((char *) (~0))
1683
1684// Compute a hash value for a native method descriptor.
1685static int
1686hash (const JNINativeMethod *method)
1687{
1688  char *ptr;
1689  int hash = 0;
1690
1691  ptr = method->name;
1692  while (*ptr)
1693    hash = (31 * hash) + *ptr++;
1694
1695  ptr = method->signature;
1696  while (*ptr)
1697    hash = (31 * hash) + *ptr++;
1698
1699  return hash;
1700}
1701
1702// Find the slot where a native method goes.
1703static JNINativeMethod *
1704nathash_find_slot (const JNINativeMethod *method)
1705{
1706  jint h = hash (method);
1707  int step = (h ^ (h >> 16)) | 1;
1708  int w = h & (nathash_size - 1);
1709  int del = -1;
1710
1711  for (;;)
1712    {
1713      JNINativeMethod *slotp = &nathash[w];
1714      if (slotp->name == NULL)
1715        {
1716          if (del >= 0)
1717            return &nathash[del];
1718          else
1719            return slotp;
1720        }
1721      else if (slotp->name == DELETED_ENTRY)
1722        del = w;
1723      else if (! strcmp (slotp->name, method->name)
1724               && ! strcmp (slotp->signature, method->signature))
1725        return slotp;
1726      w = (w + step) & (nathash_size - 1);
1727    }
1728}
1729
1730// Find a method.  Return NULL if it isn't in the hash table.
1731static void *
1732nathash_find (JNINativeMethod *method)
1733{
1734  if (nathash == NULL)
1735    return NULL;
1736  JNINativeMethod *slot = nathash_find_slot (method);
1737  if (slot->name == NULL || slot->name == DELETED_ENTRY)
1738    return NULL;
1739  return slot->fnPtr;
1740}
1741
1742static void
1743natrehash ()
1744{
1745  if (nathash == NULL)
1746    {
1747      nathash_size = 1024;
1748      nathash =
1749        (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1750                                            * sizeof (JNINativeMethod));
1751      memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1752    }
1753  else
1754    {
1755      int savesize = nathash_size;
1756      JNINativeMethod *savehash = nathash;
1757      nathash_size *= 2;
1758      nathash =
1759        (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1760                                            * sizeof (JNINativeMethod));
1761      memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1762
1763      for (int i = 0; i < savesize; ++i)
1764        {
1765          if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
1766            {
1767              JNINativeMethod *slot = nathash_find_slot (&savehash[i]);
1768              *slot = savehash[i];
1769            }
1770        }
1771    }
1772}
1773
1774static void
1775nathash_add (const JNINativeMethod *method)
1776{
1777  if (3 * nathash_count >= 2 * nathash_size)
1778    natrehash ();
1779  JNINativeMethod *slot = nathash_find_slot (method);
1780  // If the slot has a real entry in it, then there is no work to do.
1781  if (slot->name != NULL && slot->name != DELETED_ENTRY)
1782    return;
1783  // FIXME
1784  slot->name = strdup (method->name);
1785  slot->signature = strdup (method->signature);
1786  slot->fnPtr = method->fnPtr;
1787}
1788
1789static jint
1790_Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
1791                         const JNINativeMethod *methods,
1792                         jint nMethods)
1793{
1794  // Synchronize while we do the work.  This must match
1795  // synchronization in some other functions that manipulate or use
1796  // the nathash table.
1797  JvSynchronize sync (global_ref_table);
1798
1799  // Look at each descriptor given us, and find the corresponding
1800  // method in the class.
1801  for (int j = 0; j < nMethods; ++j)
1802    {
1803      bool found = false;
1804
1805      _Jv_Method *imeths = JvGetFirstMethod (klass);
1806      for (int i = 0; i < JvNumMethods (klass); ++i)
1807        {
1808          _Jv_Method *self = &imeths[i];
1809
1810          if (! strcmp (self->name->data, methods[j].name)
1811              && ! strcmp (self->signature->data, methods[j].signature))
1812            {
1813              if (! (self->accflags
1814                     & java::lang::reflect::Modifier::NATIVE))
1815                break;
1816
1817              // Found a match that is native.
1818              found = true;
1819              nathash_add (&methods[j]);
1820
1821              break;
1822            }
1823        }
1824
1825      if (! found)
1826        {
1827          jstring m = JvNewStringUTF (methods[j].name);
1828          try
1829            {
1830              env->ex =new java::lang::NoSuchMethodError (m);
1831            }
1832          catch (jthrowable t)
1833            {
1834              env->ex = t;
1835            }
1836          return JNI_ERR;
1837        }
1838    }
1839
1840  return JNI_OK;
1841}
1842
1843static jint
1844_Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
1845{
1846  // FIXME -- we could implement this.
1847  return JNI_ERR;
1848}
1849
1850
1851
1852// Add a character to the buffer, encoding properly.
1853static void
1854add_char (char *buf, jchar c, int *here)
1855{
1856  if (c == '_')
1857    {
1858      buf[(*here)++] = '_';
1859      buf[(*here)++] = '1';
1860    }
1861  else if (c == ';')
1862    {
1863      buf[(*here)++] = '_';
1864      buf[(*here)++] = '2';
1865    }
1866  else if (c == '[')
1867    {
1868      buf[(*here)++] = '_';
1869      buf[(*here)++] = '3';
1870    }
1871
1872  // Also check for `.' here because we might be passed an internal
1873  // qualified class name like `foo.bar'.
1874  else if (c == '/' || c == '.')
1875    buf[(*here)++] = '_';
1876  else if ((c >= '0' && c <= '9')
1877           || (c >= 'a' && c <= 'z')
1878           || (c >= 'A' && c <= 'Z'))
1879    buf[(*here)++] = (char) c;
1880  else
1881    {
1882      // "Unicode" character.
1883      buf[(*here)++] = '_';
1884      buf[(*here)++] = '0';
1885      for (int i = 0; i < 4; ++i)
1886        {
1887          int val = c & 0x0f;
1888          buf[(*here) + 3 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
1889          c >>= 4;
1890        }
1891      *here += 4;
1892    }
1893}
1894
1895// Compute a mangled name for a native function.  This computes the
1896// long name, and also returns an index which indicates where a NUL
1897// can be placed to create the short name.  This function assumes that
1898// the buffer is large enough for its results.
1899static void
1900mangled_name (jclass klass, _Jv_Utf8Const *func_name,
1901              _Jv_Utf8Const *signature, char *buf, int *long_start)
1902{
1903  strcpy (buf, "Java_");
1904  int here = 5;
1905
1906  // Add fully qualified class name.
1907  jchar *chars = _Jv_GetStringChars (klass->getName ());
1908  jint len = klass->getName ()->length ();
1909  for (int i = 0; i < len; ++i)
1910    add_char (buf, chars[i], &here);
1911
1912  // Don't use add_char because we need a literal `_'.
1913  buf[here++] = '_';
1914
1915  const unsigned char *fn = (const unsigned char *) func_name->data;
1916  const unsigned char *limit = fn + func_name->length;
1917  for (int i = 0; ; ++i)
1918    {
1919      int ch = UTF8_GET (fn, limit);
1920      if (ch < 0)
1921        break;
1922      add_char (buf, ch, &here);
1923    }
1924
1925  // This is where the long signature begins.
1926  *long_start = here;
1927  buf[here++] = '_';
1928  buf[here++] = '_';
1929
1930  const unsigned char *sig = (const unsigned char *) signature->data;
1931  limit = sig + signature->length;
1932  JvAssert (sig[0] == '(');
1933  ++sig;
1934  while (1)
1935    {
1936      int ch = UTF8_GET (sig, limit);
1937      if (ch == ')' || ch < 0)
1938        break;
1939      add_char (buf, ch, &here);
1940    }
1941
1942  buf[here] = '\0';
1943}
1944
1945// Return the current thread's JNIEnv; if one does not exist, create
1946// it.  Also create a new system frame for use.  This is `extern "C"'
1947// because the compiler calls it.
1948extern "C" JNIEnv *
1949_Jv_GetJNIEnvNewFrame (jclass klass)
1950{
1951  JNIEnv *env = _Jv_GetCurrentJNIEnv ();
1952  if (env == NULL)
1953    {
1954      env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
1955      env->p = &_Jv_JNIFunctions;
1956      env->ex = NULL;
1957      env->klass = klass;
1958      env->locals = NULL;
1959
1960      _Jv_SetCurrentJNIEnv (env);
1961    }
1962
1963  _Jv_JNI_LocalFrame *frame
1964    = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
1965                                                  + (FRAME_SIZE
1966                                                     * sizeof (jobject)));
1967
1968  frame->marker = MARK_SYSTEM;
1969  frame->size = FRAME_SIZE;
1970  frame->next = env->locals;
1971  env->locals = frame;
1972
1973  for (int i = 0; i < frame->size; ++i)
1974    frame->vec[i] = NULL;
1975
1976  return env;
1977}
1978
1979// Return the function which implements a particular JNI method.  If
1980// we can't find the function, we throw the appropriate exception.
1981// This is `extern "C"' because the compiler uses it.
1982extern "C" void *
1983_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
1984                     _Jv_Utf8Const *signature)
1985{
1986  char buf[10 + 6 * (name->length + signature->length)];
1987  int long_start;
1988  void *function;
1989
1990  // Synchronize on something convenient.  Right now we use the hash.
1991  JvSynchronize sync (global_ref_table);
1992
1993  // First see if we have an override in the hash table.
1994  strncpy (buf, name->data, name->length);
1995  buf[name->length] = '\0';
1996  strncpy (buf + name->length + 1, signature->data, signature->length);
1997  buf[name->length + signature->length + 1] = '\0';
1998  JNINativeMethod meth;
1999  meth.name = buf;
2000  meth.signature = buf + name->length + 1;
2001  function = nathash_find (&meth);
2002  if (function != NULL)
2003    return function;
2004
2005  // If there was no override, then look in the symbol table.
2006  mangled_name (klass, name, signature, buf, &long_start);
2007  char c = buf[long_start];
2008  buf[long_start] = '\0';
2009  function = _Jv_FindSymbolInExecutable (buf);
2010  if (function == NULL)
2011    {
2012      buf[long_start] = c;
2013      function = _Jv_FindSymbolInExecutable (buf);
2014      if (function == NULL)
2015        {
2016          jstring str = JvNewStringUTF (name->data);
2017          throw new java::lang::UnsatisfiedLinkError (str);
2018        }
2019    }
2020
2021  return function;
2022}
2023
2024#ifdef INTERPRETER
2025
2026// This function is the stub which is used to turn an ordinary (CNI)
2027// method call into a JNI call.
2028void
2029_Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this)
2030{
2031  _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
2032
2033  JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class);
2034
2035  // FIXME: we should mark every reference parameter as a local.  For
2036  // now we assume a conservative GC, and we assume that the
2037  // references are on the stack somewhere.
2038
2039  // We cache the value that we find, of course, but if we don't find
2040  // a value we don't cache that fact -- we might subsequently load a
2041  // library which finds the function in question.
2042  {
2043    // Synchronize on a convenient object to ensure sanity in case two
2044    // threads reach this point for the same function at the same
2045    // time.
2046    JvSynchronize sync (global_ref_table);
2047    if (_this->function == NULL)
2048      _this->function = _Jv_LookupJNIMethod (_this->defining_class,
2049                                             _this->self->name,
2050                                             _this->self->signature);
2051  }
2052
2053  JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0);
2054  ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)];
2055  int offset = 0;
2056
2057  // First argument is always the environment pointer.
2058  real_args[offset++].ptr = env;
2059
2060  // For a static method, we pass in the Class.  For non-static
2061  // methods, the `this' argument is already handled.
2062  if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2063    real_args[offset++].ptr = _this->defining_class;
2064
2065  // In libgcj, the callee synchronizes.
2066  jobject sync = NULL;
2067  if ((_this->self->accflags & java::lang::reflect::Modifier::SYNCHRONIZED))
2068    {
2069      if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2070        sync = _this->defining_class;
2071      else
2072        sync = (jobject) args[0].ptr;
2073      _Jv_MonitorEnter (sync);
2074    }
2075
2076  // Copy over passed-in arguments.
2077  memcpy (&real_args[offset], args, _this->args_raw_size);
2078
2079  // The actual call to the JNI function.
2080  ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
2081                ret, real_args);
2082
2083  if (sync != NULL)
2084    _Jv_MonitorExit (sync);
2085
2086  _Jv_JNI_PopSystemFrame (env);
2087}
2088
2089#endif /* INTERPRETER */
2090
2091
2092
2093//
2094// Invocation API.
2095//
2096
2097// An internal helper function.
2098static jint
2099_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv, void *args)
2100{
2101  JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (args);
2102  java::lang::ThreadGroup *group = NULL;
2103
2104  if (attach)
2105    {
2106      // FIXME: do we really want to support 1.1?
2107      if (attach->version != JNI_VERSION_1_2
2108          && attach->version != JNI_VERSION_1_1)
2109        return JNI_EVERSION;
2110
2111      JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
2112      group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
2113    }
2114
2115  // Attaching an already-attached thread is a no-op.
2116  if (_Jv_GetCurrentJNIEnv () != NULL)
2117    return 0;
2118
2119  JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
2120  if (env == NULL)
2121    return JNI_ERR;
2122  env->p = &_Jv_JNIFunctions;
2123  env->ex = NULL;
2124  env->klass = NULL;
2125  env->locals
2126    = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2127                                                  + (FRAME_SIZE
2128                                                     * sizeof (jobject)));
2129  if (env->locals == NULL)
2130    {
2131      _Jv_Free (env);
2132      return JNI_ERR;
2133    }
2134
2135  env->locals->marker = MARK_SYSTEM;
2136  env->locals->size = FRAME_SIZE;
2137  env->locals->next = NULL;
2138
2139  for (int i = 0; i < env->locals->size; ++i)
2140    env->locals->vec[i] = NULL;
2141
2142  *penv = reinterpret_cast<void *> (env);
2143
2144  // This thread might already be a Java thread -- this function might
2145  // have been called simply to set the new JNIEnv.
2146  if (_Jv_ThreadCurrent () == NULL)
2147    {
2148      try
2149        {
2150          _Jv_AttachCurrentThread (name, group);
2151        }
2152      catch (jthrowable t)
2153        {
2154          return JNI_ERR;
2155        }
2156    }
2157  _Jv_SetCurrentJNIEnv (env);
2158
2159  return 0;
2160}
2161
2162// This is the one actually used by JNI.
2163static jint
2164_Jv_JNI_AttachCurrentThread (JavaVM *vm, void **penv, void *args)
2165{
2166  return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args);
2167}
2168
2169static jint
2170_Jv_JNI_DestroyJavaVM (JavaVM *vm)
2171{
2172  JvAssert (the_vm && vm == the_vm);
2173
2174  JNIEnv *env;
2175  if (_Jv_ThreadCurrent () != NULL)
2176    {
2177      jstring main_name;
2178      // This sucks.
2179      try
2180        {
2181          main_name = JvNewStringLatin1 ("main");
2182        }
2183      catch (jthrowable t)
2184        {
2185          return JNI_ERR;
2186        }
2187
2188      jint r = _Jv_JNI_AttachCurrentThread (vm,
2189                                            main_name,
2190                                            reinterpret_cast<void **> (&env),
2191                                            NULL);
2192      if (r < 0)
2193        return r;
2194    }
2195  else
2196    env = _Jv_GetCurrentJNIEnv ();
2197
2198  _Jv_ThreadWait ();
2199
2200  // Docs say that this always returns an error code.
2201  return JNI_ERR;
2202}
2203
2204jint
2205_Jv_JNI_DetachCurrentThread (JavaVM *)
2206{
2207  jint code = _Jv_DetachCurrentThread ();
2208  return code  ? JNI_EDETACHED : 0;
2209}
2210
2211static jint
2212_Jv_JNI_GetEnv (JavaVM *, void **penv, jint version)
2213{
2214  if (_Jv_ThreadCurrent () == NULL)
2215    {
2216      *penv = NULL;
2217      return JNI_EDETACHED;
2218    }
2219
2220#ifdef ENABLE_JVMPI
2221  // Handle JVMPI requests.
2222  if (version == JVMPI_VERSION_1)
2223    {
2224      *penv = (void *) &_Jv_JVMPI_Interface;
2225      return 0;
2226    }
2227#endif
2228
2229  // FIXME: do we really want to support 1.1?
2230  if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_1)
2231    {
2232      *penv = NULL;
2233      return JNI_EVERSION;
2234    }
2235
2236  *penv = (void *) _Jv_GetCurrentJNIEnv ();
2237  return 0;
2238}
2239
2240jint
2241JNI_GetDefaultJavaVMInitArgs (void *args)
2242{
2243  jint version = * (jint *) args;
2244  // Here we only support 1.2.
2245  if (version != JNI_VERSION_1_2)
2246    return JNI_EVERSION;
2247
2248  JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2249  ia->version = JNI_VERSION_1_2;
2250  ia->nOptions = 0;
2251  ia->options = NULL;
2252  ia->ignoreUnrecognized = true;
2253
2254  return 0;
2255}
2256
2257jint
2258JNI_CreateJavaVM (JavaVM **vm, void **penv, void *args)
2259{
2260  JvAssert (! the_vm);
2261
2262  _Jv_CreateJavaVM (NULL);
2263
2264  // FIXME: synchronize
2265  JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2266  if (nvm == NULL)
2267    return JNI_ERR;
2268  nvm->functions = &_Jv_JNI_InvokeFunctions;
2269
2270  // Parse the arguments.
2271  if (args != NULL)
2272    {
2273      jint version = * (jint *) args;
2274      // We only support 1.2.
2275      if (version != JNI_VERSION_1_2)
2276        return JNI_EVERSION;
2277      JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2278      for (int i = 0; i < ia->nOptions; ++i)
2279        {
2280          if (! strcmp (ia->options[i].optionString, "vfprintf")
2281              || ! strcmp (ia->options[i].optionString, "exit")
2282              || ! strcmp (ia->options[i].optionString, "abort"))
2283            {
2284              // We are required to recognize these, but for now we
2285              // don't handle them in any way.  FIXME.
2286              continue;
2287            }
2288          else if (! strncmp (ia->options[i].optionString,
2289                              "-verbose", sizeof ("-verbose") - 1))
2290            {
2291              // We don't do anything with this option either.  We
2292              // might want to make sure the argument is valid, but we
2293              // don't really care all that much for now.
2294              continue;
2295            }
2296          else if (! strncmp (ia->options[i].optionString, "-D", 2))
2297            {
2298              // FIXME.
2299              continue;
2300            }
2301          else if (ia->ignoreUnrecognized)
2302            {
2303              if (ia->options[i].optionString[0] == '_'
2304                  || ! strncmp (ia->options[i].optionString, "-X", 2))
2305                continue;
2306            }
2307
2308          return JNI_ERR;
2309        }
2310    }
2311
2312  jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL);
2313  if (r < 0)
2314    return r;
2315
2316  the_vm = nvm;
2317  *vm = the_vm;
2318
2319  return 0;
2320}
2321
2322jint
2323JNI_GetCreatedJavaVMs (JavaVM **vm_buffer, jsize buf_len, jsize *n_vms)
2324{
2325  if (buf_len <= 0)
2326    return JNI_ERR;
2327
2328  // We only support a single VM.
2329  if (the_vm != NULL)
2330    {
2331      vm_buffer[0] = the_vm;
2332      *n_vms = 1;
2333    }
2334  else
2335    *n_vms = 0;
2336  return 0;
2337}
2338
2339JavaVM *
2340_Jv_GetJavaVM ()
2341{
2342  // FIXME: synchronize
2343  if (! the_vm)
2344    {
2345      JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2346      if (nvm != NULL)
2347        nvm->functions = &_Jv_JNI_InvokeFunctions;
2348      the_vm = nvm;
2349    }
2350
2351  // If this is a Java thread, we want to make sure it has an
2352  // associated JNIEnv.
2353  if (_Jv_ThreadCurrent () != NULL)
2354    {
2355      void *ignore;
2356      _Jv_JNI_AttachCurrentThread (the_vm, &ignore, NULL);
2357    }
2358
2359  return the_vm;
2360}
2361
2362static jint
2363_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
2364{
2365  *vm = _Jv_GetJavaVM ();
2366  return *vm == NULL ? JNI_ERR : JNI_OK;
2367}
2368
2369
2370
2371#define RESERVED NULL
2372
2373struct JNINativeInterface _Jv_JNIFunctions =
2374{
2375  RESERVED,
2376  RESERVED,
2377  RESERVED,
2378  RESERVED,
2379  _Jv_JNI_GetVersion,           // GetVersion
2380  _Jv_JNI_DefineClass,          // DefineClass
2381  _Jv_JNI_FindClass,            // FindClass
2382  _Jv_JNI_FromReflectedMethod,  // FromReflectedMethod
2383  _Jv_JNI_FromReflectedField,   // FromReflectedField
2384  _Jv_JNI_ToReflectedMethod,    // ToReflectedMethod
2385  _Jv_JNI_GetSuperclass,        // GetSuperclass
2386  _Jv_JNI_IsAssignableFrom,     // IsAssignableFrom
2387  _Jv_JNI_ToReflectedField,     // ToReflectedField
2388  _Jv_JNI_Throw,                // Throw
2389  _Jv_JNI_ThrowNew,             // ThrowNew
2390  _Jv_JNI_ExceptionOccurred,    // ExceptionOccurred
2391  _Jv_JNI_ExceptionDescribe,    // ExceptionDescribe
2392  _Jv_JNI_ExceptionClear,       // ExceptionClear
2393  _Jv_JNI_FatalError,           // FatalError
2394
2395  _Jv_JNI_PushLocalFrame,       // PushLocalFrame
2396  _Jv_JNI_PopLocalFrame,        // PopLocalFrame
2397  _Jv_JNI_NewGlobalRef,         // NewGlobalRef
2398  _Jv_JNI_DeleteGlobalRef,      // DeleteGlobalRef
2399  _Jv_JNI_DeleteLocalRef,       // DeleteLocalRef
2400
2401  _Jv_JNI_IsSameObject,         // IsSameObject
2402
2403  _Jv_JNI_NewLocalRef,          // NewLocalRef
2404  _Jv_JNI_EnsureLocalCapacity,  // EnsureLocalCapacity
2405
2406  _Jv_JNI_AllocObject,              // AllocObject
2407  _Jv_JNI_NewObject,                // NewObject
2408  _Jv_JNI_NewObjectV,               // NewObjectV
2409  _Jv_JNI_NewObjectA,               // NewObjectA
2410  _Jv_JNI_GetObjectClass,           // GetObjectClass
2411  _Jv_JNI_IsInstanceOf,             // IsInstanceOf
2412  _Jv_JNI_GetAnyMethodID<false>,    // GetMethodID
2413
2414  _Jv_JNI_CallMethod<jobject>,          // CallObjectMethod
2415  _Jv_JNI_CallMethodV<jobject>,         // CallObjectMethodV
2416  _Jv_JNI_CallMethodA<jobject>,         // CallObjectMethodA
2417  _Jv_JNI_CallMethod<jboolean>,         // CallBooleanMethod
2418  _Jv_JNI_CallMethodV<jboolean>,        // CallBooleanMethodV
2419  _Jv_JNI_CallMethodA<jboolean>,        // CallBooleanMethodA
2420  _Jv_JNI_CallMethod<jbyte>,            // CallByteMethod
2421  _Jv_JNI_CallMethodV<jbyte>,           // CallByteMethodV
2422  _Jv_JNI_CallMethodA<jbyte>,           // CallByteMethodA
2423  _Jv_JNI_CallMethod<jchar>,            // CallCharMethod
2424  _Jv_JNI_CallMethodV<jchar>,           // CallCharMethodV
2425  _Jv_JNI_CallMethodA<jchar>,           // CallCharMethodA
2426  _Jv_JNI_CallMethod<jshort>,           // CallShortMethod
2427  _Jv_JNI_CallMethodV<jshort>,          // CallShortMethodV
2428  _Jv_JNI_CallMethodA<jshort>,          // CallShortMethodA
2429  _Jv_JNI_CallMethod<jint>,             // CallIntMethod
2430  _Jv_JNI_CallMethodV<jint>,            // CallIntMethodV
2431  _Jv_JNI_CallMethodA<jint>,            // CallIntMethodA
2432  _Jv_JNI_CallMethod<jlong>,            // CallLongMethod
2433  _Jv_JNI_CallMethodV<jlong>,           // CallLongMethodV
2434  _Jv_JNI_CallMethodA<jlong>,           // CallLongMethodA
2435  _Jv_JNI_CallMethod<jfloat>,           // CallFloatMethod
2436  _Jv_JNI_CallMethodV<jfloat>,          // CallFloatMethodV
2437  _Jv_JNI_CallMethodA<jfloat>,          // CallFloatMethodA
2438  _Jv_JNI_CallMethod<jdouble>,          // CallDoubleMethod
2439  _Jv_JNI_CallMethodV<jdouble>,         // CallDoubleMethodV
2440  _Jv_JNI_CallMethodA<jdouble>,         // CallDoubleMethodA
2441  _Jv_JNI_CallVoidMethod,               // CallVoidMethod
2442  _Jv_JNI_CallVoidMethodV,              // CallVoidMethodV
2443  _Jv_JNI_CallVoidMethodA,              // CallVoidMethodA
2444
2445  // Nonvirtual method invocation functions follow.
2446  _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,   // CallNonvirtualObjectMethod
2447  _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,  // CallNonvirtualObjectMethodV
2448  _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,  // CallNonvirtualObjectMethodA
2449  _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,  // CallNonvirtualBooleanMethod
2450  _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodV
2451  _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodA
2452  _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,     // CallNonvirtualByteMethod
2453  _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,    // CallNonvirtualByteMethodV
2454  _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,    // CallNonvirtualByteMethodA
2455  _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,     // CallNonvirtualCharMethod
2456  _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,    // CallNonvirtualCharMethodV
2457  _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,    // CallNonvirtualCharMethodA
2458  _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,    // CallNonvirtualShortMethod
2459  _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,   // CallNonvirtualShortMethodV
2460  _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,   // CallNonvirtualShortMethodA
2461  _Jv_JNI_CallAnyMethod<jint, nonvirtual>,      // CallNonvirtualIntMethod
2462  _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,     // CallNonvirtualIntMethodV
2463  _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,     // CallNonvirtualIntMethodA
2464  _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,     // CallNonvirtualLongMethod
2465  _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,    // CallNonvirtualLongMethodV
2466  _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,    // CallNonvirtualLongMethodA
2467  _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,    // CallNonvirtualFloatMethod
2468  _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodV
2469  _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodA
2470  _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,   // CallNonvirtualDoubleMethod
2471  _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodV
2472  _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodA
2473  _Jv_JNI_CallAnyVoidMethod<nonvirtual>,        // CallNonvirtualVoidMethod
2474  _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,       // CallNonvirtualVoidMethodV
2475  _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,       // CallNonvirtualVoidMethodA
2476
2477  _Jv_JNI_GetAnyFieldID<false>, // GetFieldID
2478  _Jv_JNI_GetField<jobject>,    // GetObjectField
2479  _Jv_JNI_GetField<jboolean>,   // GetBooleanField
2480  _Jv_JNI_GetField<jbyte>,      // GetByteField
2481  _Jv_JNI_GetField<jchar>,      // GetCharField
2482  _Jv_JNI_GetField<jshort>,     // GetShortField
2483  _Jv_JNI_GetField<jint>,       // GetIntField
2484  _Jv_JNI_GetField<jlong>,      // GetLongField
2485  _Jv_JNI_GetField<jfloat>,     // GetFloatField
2486  _Jv_JNI_GetField<jdouble>,    // GetDoubleField
2487  _Jv_JNI_SetField,             // SetObjectField
2488  _Jv_JNI_SetField,             // SetBooleanField
2489  _Jv_JNI_SetField,             // SetByteField
2490  _Jv_JNI_SetField,             // SetCharField
2491  _Jv_JNI_SetField,             // SetShortField
2492  _Jv_JNI_SetField,             // SetIntField
2493  _Jv_JNI_SetField,             // SetLongField
2494  _Jv_JNI_SetField,             // SetFloatField
2495  _Jv_JNI_SetField,             // SetDoubleField
2496  _Jv_JNI_GetAnyMethodID<true>, // GetStaticMethodID
2497
2498  _Jv_JNI_CallStaticMethod<jobject>,      // CallStaticObjectMethod
2499  _Jv_JNI_CallStaticMethodV<jobject>,     // CallStaticObjectMethodV
2500  _Jv_JNI_CallStaticMethodA<jobject>,     // CallStaticObjectMethodA
2501  _Jv_JNI_CallStaticMethod<jboolean>,     // CallStaticBooleanMethod
2502  _Jv_JNI_CallStaticMethodV<jboolean>,    // CallStaticBooleanMethodV
2503  _Jv_JNI_CallStaticMethodA<jboolean>,    // CallStaticBooleanMethodA
2504  _Jv_JNI_CallStaticMethod<jbyte>,        // CallStaticByteMethod
2505  _Jv_JNI_CallStaticMethodV<jbyte>,       // CallStaticByteMethodV
2506  _Jv_JNI_CallStaticMethodA<jbyte>,       // CallStaticByteMethodA
2507  _Jv_JNI_CallStaticMethod<jchar>,        // CallStaticCharMethod
2508  _Jv_JNI_CallStaticMethodV<jchar>,       // CallStaticCharMethodV
2509  _Jv_JNI_CallStaticMethodA<jchar>,       // CallStaticCharMethodA
2510  _Jv_JNI_CallStaticMethod<jshort>,       // CallStaticShortMethod
2511  _Jv_JNI_CallStaticMethodV<jshort>,      // CallStaticShortMethodV
2512  _Jv_JNI_CallStaticMethodA<jshort>,      // CallStaticShortMethodA
2513  _Jv_JNI_CallStaticMethod<jint>,         // CallStaticIntMethod
2514  _Jv_JNI_CallStaticMethodV<jint>,        // CallStaticIntMethodV
2515  _Jv_JNI_CallStaticMethodA<jint>,        // CallStaticIntMethodA
2516  _Jv_JNI_CallStaticMethod<jlong>,        // CallStaticLongMethod
2517  _Jv_JNI_CallStaticMethodV<jlong>,       // CallStaticLongMethodV
2518  _Jv_JNI_CallStaticMethodA<jlong>,       // CallStaticLongMethodA
2519  _Jv_JNI_CallStaticMethod<jfloat>,       // CallStaticFloatMethod
2520  _Jv_JNI_CallStaticMethodV<jfloat>,      // CallStaticFloatMethodV
2521  _Jv_JNI_CallStaticMethodA<jfloat>,      // CallStaticFloatMethodA
2522  _Jv_JNI_CallStaticMethod<jdouble>,      // CallStaticDoubleMethod
2523  _Jv_JNI_CallStaticMethodV<jdouble>,     // CallStaticDoubleMethodV
2524  _Jv_JNI_CallStaticMethodA<jdouble>,     // CallStaticDoubleMethodA
2525  _Jv_JNI_CallStaticVoidMethod,           // CallStaticVoidMethod
2526  _Jv_JNI_CallStaticVoidMethodV,          // CallStaticVoidMethodV
2527  _Jv_JNI_CallStaticVoidMethodA,          // CallStaticVoidMethodA
2528
2529  _Jv_JNI_GetAnyFieldID<true>,         // GetStaticFieldID
2530  _Jv_JNI_GetStaticField<jobject>,     // GetStaticObjectField
2531  _Jv_JNI_GetStaticField<jboolean>,    // GetStaticBooleanField
2532  _Jv_JNI_GetStaticField<jbyte>,       // GetStaticByteField
2533  _Jv_JNI_GetStaticField<jchar>,       // GetStaticCharField
2534  _Jv_JNI_GetStaticField<jshort>,      // GetStaticShortField
2535  _Jv_JNI_GetStaticField<jint>,        // GetStaticIntField
2536  _Jv_JNI_GetStaticField<jlong>,       // GetStaticLongField
2537  _Jv_JNI_GetStaticField<jfloat>,      // GetStaticFloatField
2538  _Jv_JNI_GetStaticField<jdouble>,     // GetStaticDoubleField
2539  _Jv_JNI_SetStaticField,              // SetStaticObjectField
2540  _Jv_JNI_SetStaticField,              // SetStaticBooleanField
2541  _Jv_JNI_SetStaticField,              // SetStaticByteField
2542  _Jv_JNI_SetStaticField,              // SetStaticCharField
2543  _Jv_JNI_SetStaticField,              // SetStaticShortField
2544  _Jv_JNI_SetStaticField,              // SetStaticIntField
2545  _Jv_JNI_SetStaticField,              // SetStaticLongField
2546  _Jv_JNI_SetStaticField,              // SetStaticFloatField
2547  _Jv_JNI_SetStaticField,              // SetStaticDoubleField
2548  _Jv_JNI_NewString,                   // NewString
2549  _Jv_JNI_GetStringLength,             // GetStringLength
2550  _Jv_JNI_GetStringChars,              // GetStringChars
2551  _Jv_JNI_ReleaseStringChars,          // ReleaseStringChars
2552  _Jv_JNI_NewStringUTF,                // NewStringUTF
2553  _Jv_JNI_GetStringUTFLength,          // GetStringUTFLength
2554  _Jv_JNI_GetStringUTFChars,           // GetStringUTFLength
2555  _Jv_JNI_ReleaseStringUTFChars,       // ReleaseStringUTFChars
2556  _Jv_JNI_GetArrayLength,              // GetArrayLength
2557  _Jv_JNI_NewObjectArray,              // NewObjectArray
2558  _Jv_JNI_GetObjectArrayElement,       // GetObjectArrayElement
2559  _Jv_JNI_SetObjectArrayElement,       // SetObjectArrayElement
2560  _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
2561                                                            // NewBooleanArray
2562  _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,     // NewByteArray
2563  _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,     // NewCharArray
2564  _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,   // NewShortArray
2565  _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,       // NewIntArray
2566  _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,     // NewLongArray
2567  _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,   // NewFloatArray
2568  _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>, // NewDoubleArray
2569  _Jv_JNI_GetPrimitiveArrayElements,        // GetBooleanArrayElements
2570  _Jv_JNI_GetPrimitiveArrayElements,        // GetByteArrayElements
2571  _Jv_JNI_GetPrimitiveArrayElements,        // GetCharArrayElements
2572  _Jv_JNI_GetPrimitiveArrayElements,        // GetShortArrayElements
2573  _Jv_JNI_GetPrimitiveArrayElements,        // GetIntArrayElements
2574  _Jv_JNI_GetPrimitiveArrayElements,        // GetLongArrayElements
2575  _Jv_JNI_GetPrimitiveArrayElements,        // GetFloatArrayElements
2576  _Jv_JNI_GetPrimitiveArrayElements,        // GetDoubleArrayElements
2577  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseBooleanArrayElements
2578  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseByteArrayElements
2579  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseCharArrayElements
2580  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseShortArrayElements
2581  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseIntArrayElements
2582  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseLongArrayElements
2583  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseFloatArrayElements
2584  _Jv_JNI_ReleasePrimitiveArrayElements,    // ReleaseDoubleArrayElements
2585  _Jv_JNI_GetPrimitiveArrayRegion,          // GetBooleanArrayRegion
2586  _Jv_JNI_GetPrimitiveArrayRegion,          // GetByteArrayRegion
2587  _Jv_JNI_GetPrimitiveArrayRegion,          // GetCharArrayRegion
2588  _Jv_JNI_GetPrimitiveArrayRegion,          // GetShortArrayRegion
2589  _Jv_JNI_GetPrimitiveArrayRegion,          // GetIntArrayRegion
2590  _Jv_JNI_GetPrimitiveArrayRegion,          // GetLongArrayRegion
2591  _Jv_JNI_GetPrimitiveArrayRegion,          // GetFloatArrayRegion
2592  _Jv_JNI_GetPrimitiveArrayRegion,          // GetDoubleArrayRegion
2593  _Jv_JNI_SetPrimitiveArrayRegion,          // SetBooleanArrayRegion
2594  _Jv_JNI_SetPrimitiveArrayRegion,          // SetByteArrayRegion
2595  _Jv_JNI_SetPrimitiveArrayRegion,          // SetCharArrayRegion
2596  _Jv_JNI_SetPrimitiveArrayRegion,          // SetShortArrayRegion
2597  _Jv_JNI_SetPrimitiveArrayRegion,          // SetIntArrayRegion
2598  _Jv_JNI_SetPrimitiveArrayRegion,          // SetLongArrayRegion
2599  _Jv_JNI_SetPrimitiveArrayRegion,          // SetFloatArrayRegion
2600  _Jv_JNI_SetPrimitiveArrayRegion,          // SetDoubleArrayRegion
2601  _Jv_JNI_RegisterNatives,                  // RegisterNatives
2602  _Jv_JNI_UnregisterNatives,                // UnregisterNatives
2603  _Jv_JNI_MonitorEnter,                     // MonitorEnter
2604  _Jv_JNI_MonitorExit,                      // MonitorExit
2605  _Jv_JNI_GetJavaVM,                        // GetJavaVM
2606
2607  _Jv_JNI_GetStringRegion,                  // GetStringRegion
2608  _Jv_JNI_GetStringUTFRegion,               // GetStringUTFRegion
2609  _Jv_JNI_GetPrimitiveArrayCritical,        // GetPrimitiveArrayCritical
2610  _Jv_JNI_ReleasePrimitiveArrayCritical,    // ReleasePrimitiveArrayCritical
2611  _Jv_JNI_GetStringCritical,                // GetStringCritical
2612  _Jv_JNI_ReleaseStringCritical,            // ReleaseStringCritical
2613
2614  _Jv_JNI_NewWeakGlobalRef,                 // NewWeakGlobalRef
2615  _Jv_JNI_DeleteWeakGlobalRef,              // DeleteWeakGlobalRef
2616
2617  _Jv_JNI_ExceptionCheck
2618};
2619
2620struct JNIInvokeInterface _Jv_JNI_InvokeFunctions =
2621{
2622  RESERVED,
2623  RESERVED,
2624  RESERVED,
2625
2626  _Jv_JNI_DestroyJavaVM,
2627  _Jv_JNI_AttachCurrentThread,
2628  _Jv_JNI_DetachCurrentThread,
2629  _Jv_JNI_GetEnv
2630};
Note: See TracBrowser for help on using the repository browser.