e55452bee087e494e6fe96e6ce28e882c76fd9c9
[cacao.git] / src / native / native.c
1 /* src/native/native.c - native library support
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include <stdint.h>
32
33 #include "vm/types.h"
34
35 #include "mm/memory.h"
36
37 #include "native/jni.hpp"
38 #include "native/native.h"
39
40 #include "native/vm/nativevm.h"
41
42 #include "threads/lock-common.h"
43
44 #include "toolbox/avl.h"
45 #include "toolbox/hashtable.h"
46 #include "toolbox/logging.h"
47
48 #include "vm/builtin.h"
49 #include "vm/exceptions.hpp"
50 #include "vm/global.h"
51 #include "vm/globals.hpp"
52 #include "vm/loader.h"
53 #include "vm/options.h"
54 #include "vm/os.hpp"
55 #include "vm/resolve.h"
56 #include "vm/string.hpp"
57 #include "vm/vm.hpp"
58
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/jit.h"
61
62 #if defined(ENABLE_JVMTI)
63 #include "native/jvmti/cacaodbg.h"
64 #endif
65
66
67 /* global variables ***********************************************************/
68
69 static avl_tree_t *tree_native_methods;
70
71 #if defined(ENABLE_DL)
72 static hashtable *hashtable_library;
73 #endif
74
75
76 /* prototypes *****************************************************************/
77
78 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
79
80
81 /* native_init *****************************************************************
82
83    Initializes the native subsystem.
84
85 *******************************************************************************/
86
87 bool native_init(void)
88 {
89         TRACESUBSYSTEMINITIALIZATION("native_init");
90
91 #if defined(ENABLE_DL)
92         /* initialize library hashtable, 10 entries should be enough */
93
94         hashtable_library = NEW(hashtable);
95
96         hashtable_create(hashtable_library, 10);
97 #endif
98
99         /* initialize the native methods table */
100
101         tree_native_methods = avl_create(&native_tree_native_methods_comparator);
102
103         /* everything's ok */
104
105         return true;
106 }
107
108
109 /* native_tree_native_methods_comparator ***************************************
110
111    Comparison function for AVL tree of native methods.
112
113    IN:
114        treenode....node in the tree
115            node........node to compare with tree-node
116
117    RETURN VALUE:
118        -1, 0, +1
119
120 *******************************************************************************/
121
122 static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
123 {
124         const native_methods_node_t *treenmn;
125         const native_methods_node_t *nmn;
126
127         treenmn = treenode;
128         nmn     = node;
129
130         /* these are for walking the tree */
131
132         if (treenmn->classname < nmn->classname)
133                 return -1;
134         else if (treenmn->classname > nmn->classname)
135                 return 1;
136
137         if (treenmn->name < nmn->name)
138                 return -1;
139         else if (treenmn->name > nmn->name)
140                 return 1;
141
142         if (treenmn->descriptor < nmn->descriptor)
143                 return -1;
144         else if (treenmn->descriptor > nmn->descriptor)
145                 return 1;
146
147         /* all pointers are equal, we have found the entry */
148
149         return 0;
150 }
151
152
153 /* native_make_overloaded_function *********************************************
154
155    XXX
156
157 *******************************************************************************/
158
159 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
160 {
161         char *newname;
162         s4    namelen;
163         char *utf_ptr;
164         u2    c;
165         s4    i;
166         utf  *u;
167         int32_t dumpmarker;
168
169         /* mark memory */
170
171         DMARKER;
172
173         utf_ptr = descriptor->text;
174         namelen = strlen(name->text) + strlen("__") + strlen("0");
175
176         /* calculate additional length */
177
178         while ((c = utf_nextu2(&utf_ptr)) != ')') {
179                 switch (c) {
180                 case 'Z':
181                 case 'B':
182                 case 'C':
183                 case 'S':
184                 case 'I':
185                 case 'J':
186                 case 'F':
187                 case 'D':
188                         namelen++;
189                         break;
190                 case '[':
191                         namelen += 2;
192                         break;
193                 case 'L':
194                         namelen++;
195                         while (utf_nextu2(&utf_ptr) != ';')
196                                 namelen++;
197                         namelen += 2;
198                         break;
199                 case '(':
200                         break;
201                 default:
202                         assert(0);
203                 }
204         }
205
206         /* reallocate memory */
207
208         i = strlen(name->text);
209
210         newname = DMNEW(char, namelen);
211         MCOPY(newname, name->text, char, i);
212
213         utf_ptr = descriptor->text;
214
215         newname[i++] = '_';
216         newname[i++] = '_';
217
218         while ((c = utf_nextu2(&utf_ptr)) != ')') {
219                 switch (c) {
220                 case 'Z':
221                 case 'B':
222                 case 'C':
223                 case 'S':
224                 case 'J':
225                 case 'I':
226                 case 'F':
227                 case 'D':
228                         newname[i++] = c;
229                         break;
230                 case '[':
231                         newname[i++] = '_';
232                         newname[i++] = '3';
233                         break;
234                 case 'L':
235                         newname[i++] = 'L';
236                         while ((c = utf_nextu2(&utf_ptr)) != ';')
237                                 if (((c >= 'a') && (c <= 'z')) ||
238                                         ((c >= 'A') && (c <= 'Z')) ||
239                                         ((c >= '0') && (c <= '9')))
240                                         newname[i++] = c;
241                                 else
242                                         newname[i++] = '_';
243                         newname[i++] = '_';
244                         newname[i++] = '2';
245                         break;
246                 case '(':
247                         break;
248                 default:
249                         assert(0);
250                 }
251         }
252
253         /* close string */
254
255         newname[i] = '\0';
256
257         /* make a utf-string */
258
259         u = utf_new_char(newname);
260
261         /* release memory */
262
263         DRELEASE;
264
265         return u;
266 }
267
268
269 /* native_insert_char **********************************************************
270
271    Inserts the passed UTF character into the native method name.  If
272    necessary it is escaped properly.
273
274 *******************************************************************************/
275
276 static s4 native_insert_char(char *name, u4 pos, u2 c)
277 {
278         s4 val;
279         s4 i;
280
281         switch (c) {
282         case '/':
283         case '.':
284                 /* replace '/' or '.' with '_' */
285                 name[pos] = '_';
286                 break;
287
288         case '_':
289                 /* escape sequence for '_' is '_1' */
290                 name[pos]   = '_';
291                 name[++pos] = '1';
292                 break;
293
294         case ';':
295                 /* escape sequence for ';' is '_2' */
296                 name[pos]   = '_';
297                 name[++pos] = '2';
298                 break;
299
300         case '[':
301                 /* escape sequence for '[' is '_1' */
302                 name[pos]   = '_';
303                 name[++pos] = '3';
304                 break;
305
306         default:
307                 if (isalnum(c))
308                         name[pos] = c;
309                 else {
310                         /* unicode character */
311                         name[pos]   = '_';
312                         name[++pos] = '0';
313
314                         for (i = 0; i < 4; ++i) {
315                                 val = c & 0x0f;
316                                 name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
317                                 c >>= 4;
318                         }
319
320                         pos += 4;
321                 }
322                 break;
323         }
324
325         /* return the new buffer index */
326
327         return pos;
328 }
329
330
331 /* native_method_symbol ********************************************************
332
333    Generate a method-symbol string out of the class name and the
334    method name.
335
336 *******************************************************************************/
337
338 static utf *native_method_symbol(utf *classname, utf *methodname)
339 {
340         char *name;
341         s4    namelen;
342         char *utf_ptr;
343         char *utf_endptr;
344         u2    c;
345         u4    pos;
346         utf  *u;
347         int32_t dumpmarker;
348
349         /* mark memory */
350
351         DMARKER;
352
353         /* Calculate length of native function name.  We multiply the
354            class and method name length by 6 as this is the maxium
355            escape-sequence that can be generated (unicode). */
356
357         namelen =
358                 strlen("Java_") +
359                 utf_get_number_of_u2s(classname) * 6 +
360                 strlen("_") +
361                 utf_get_number_of_u2s(methodname) * 6 +
362                 strlen("0");
363
364         /* allocate memory */
365
366         name = DMNEW(char, namelen);
367
368         /* generate name of native functions */
369
370         strcpy(name, "Java_");
371         pos = strlen("Java_");
372
373         utf_ptr    = classname->text;
374         utf_endptr = UTF_END(classname);
375
376         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
377                 c   = *utf_ptr;
378                 pos = native_insert_char(name, pos, c);
379         }
380
381         /* seperator between class and method */
382
383         name[pos++] = '_';
384
385         utf_ptr    = methodname->text;
386         utf_endptr = UTF_END(methodname);
387
388         for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
389                 c   = *utf_ptr;
390                 pos = native_insert_char(name, pos, c);
391         }
392
393         /* close string */
394
395         name[pos] = '\0';
396
397         /* check for an buffer overflow */
398
399         assert(pos <= namelen);
400
401         /* make a utf-string */
402
403         u = utf_new_char(name);
404
405         /* release memory */
406
407         DRELEASE;
408
409         return u;
410 }
411
412
413 /* native_method_register ******************************************************
414
415    Register a native method in the native method table.
416
417 *******************************************************************************/
418
419 void native_method_register(utf *classname, const JNINativeMethod *methods,
420                                                         int32_t count)
421 {
422         native_methods_node_t *nmn;
423         utf                   *name;
424         utf                   *descriptor;
425         int32_t                i;
426
427         /* insert all methods passed */
428
429         for (i = 0; i < count; i++) {
430                 if (opt_verbosejni) {
431                         printf("[Registering JNI native method ");
432                         utf_display_printable_ascii_classname(classname);
433                         printf(".%s]\n", methods[i].name);
434                 }
435
436                 /* generate the utf8 names */
437
438                 name       = utf_new_char(methods[i].name);
439                 descriptor = utf_new_char(methods[i].signature);
440
441                 /* allocate a new tree node */
442
443                 nmn = NEW(native_methods_node_t);
444
445                 nmn->classname  = classname;
446                 nmn->name       = name;
447                 nmn->descriptor = descriptor;
448                 nmn->function   = (functionptr) (ptrint) methods[i].fnPtr;
449
450                 /* insert the method into the tree */
451
452                 avl_insert(tree_native_methods, nmn);
453         }
454 }
455
456
457 /* native_method_find **********************************************************
458
459    Find a native method in the native method table.
460
461 *******************************************************************************/
462
463 static functionptr native_method_find(methodinfo *m)
464 {
465         native_methods_node_t  tmpnmn;
466         native_methods_node_t *nmn;
467
468         /* fill the temporary structure used for searching the tree */
469
470         tmpnmn.classname  = m->clazz->name;
471         tmpnmn.name       = m->name;
472         tmpnmn.descriptor = m->descriptor;
473
474         /* find the entry in the AVL-tree */
475
476         nmn = avl_find(tree_native_methods, &tmpnmn);
477
478         if (nmn == NULL)
479                 return NULL;
480
481         return nmn->function;
482 }
483
484
485 /* native_method_resolve *******************************************************
486
487    Resolves a native method, maybe from a dynamic library.
488
489    IN:
490        m ... methodinfo of the native Java method to resolve
491
492    RESULT:
493        pointer to the resolved method (symbol)
494
495 *******************************************************************************/
496
497 functionptr native_method_resolve(methodinfo *m)
498 {
499         utf                            *name;
500         utf                            *newname;
501         functionptr                     f;
502 #if defined(ENABLE_DL)
503         classloader_t                  *cl;
504         hashtable_library_loader_entry *le;
505         hashtable_library_name_entry   *ne;
506         u4                              key;    /* hashkey                        */
507         u4                              slot;   /* slot in hashtable              */
508 #endif
509 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
510         methodinfo                     *method_findNative;
511         java_handle_t                  *s;
512 #endif
513
514         /* verbose output */
515
516         if (opt_verbosejni) {
517                 printf("[Dynamic-linking native method ");
518                 utf_display_printable_ascii_classname(m->clazz->name);
519                 printf(".");
520                 utf_display_printable_ascii(m->name);
521                 printf(" ... ");
522         }
523
524         /* generate method symbol string */
525
526         name = native_method_symbol(m->clazz->name, m->name);
527
528         /* generate overloaded function (having the types in it's name)           */
529
530         newname = native_make_overloaded_function(name, m->descriptor);
531
532         /* check the library hash entries of the classloader of the
533            methods's class  */
534
535         f = NULL;
536
537 #if defined(ENABLE_DL)
538         /* Get the classloader. */
539
540         cl = class_get_classloader(m->clazz);
541
542         /* normally addresses are aligned to 4, 8 or 16 bytes */
543
544         key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
545         slot = key & (hashtable_library->size - 1);
546         le   = hashtable_library->ptr[slot];
547
548         /* iterate through loaders in this hash slot */
549
550         while ((le != NULL) && (f == NULL)) {
551                 /* iterate through names in this loader */
552
553                 ne = le->namelink;
554                         
555                 while ((ne != NULL) && (f == NULL)) {
556                         f = (functionptr) (ptrint) os_dlsym(ne->handle, name->text);
557
558                         if (f == NULL)
559                                 f = (functionptr) (ptrint) os_dlsym(ne->handle, newname->text);
560
561                         ne = ne->hashlink;
562                 }
563
564                 le = le->hashlink;
565         }
566
567 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
568         if (f == NULL) {
569                 /* We can resolve the function directly from
570                    java.lang.ClassLoader as it's a static function. */
571                 /* XXX should be done in native_init */
572
573                 method_findNative =
574                         class_resolveclassmethod(class_java_lang_ClassLoader,
575                                                                          utf_findNative,
576                                                                          utf_java_lang_ClassLoader_java_lang_String__J,
577                                                                          class_java_lang_ClassLoader,
578                                                                          true);
579
580                 if (method_findNative == NULL)
581                         return NULL;
582
583                 /* try the normal name */
584
585                 s = javastring_new(name);
586
587                 f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
588                                                                                                                  NULL, cl, s);
589
590                 /* if not found, try the mangled name */
591
592                 if (f == NULL) {
593                         s = javastring_new(newname);
594
595                         f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
596                                                                                                                          NULL, cl, s);
597                 }
598         }
599 # endif
600
601         if (f != NULL)
602                 if (opt_verbosejni)
603                         printf("JNI ]\n");
604 #endif
605
606         /* If not found, try to find the native function symbol in the
607            main program. */
608
609         if (f == NULL) {
610                 f = native_method_find(m);
611
612                 if (f != NULL)
613                         if (opt_verbosejni)
614                                 printf("internal ]\n");
615         }
616
617 #if defined(ENABLE_JVMTI)
618         /* fire Native Method Bind event */
619         if (jvmti) jvmti_NativeMethodBind(m, f, &f);
620 #endif
621
622         /* no symbol found? throw exception */
623
624         if (f == NULL) {
625                 if (opt_verbosejni)
626                         printf("failed ]\n");
627
628                 exceptions_throw_unsatisfiedlinkerror(m->name);
629         }
630
631         return f;
632 }
633
634
635 /* native_library_open *********************************************************
636
637    Open a native library with the given utf8 name.
638
639    IN:
640        filename ... filename of the library to open
641
642    RETURN:
643        handle of the opened library
644
645 *******************************************************************************/
646
647 #if defined(ENABLE_DL)
648 void* native_library_open(utf *filename)
649 {
650         void* handle;
651
652         if (opt_verbosejni) {
653                 printf("[Loading native library ");
654                 utf_display_printable_ascii(filename);
655                 printf(" ... ");
656         }
657
658         /* try to open the library */
659
660         handle = os_dlopen(filename->text, RTLD_LAZY);
661
662         if (handle == NULL) {
663                 if (opt_verbosejni)
664                         printf("failed ]\n");
665
666                 if (opt_verbose) {
667                         log_start();
668                         log_print("native_library_open: os_dlopen failed: ");
669                         log_print(dlerror());
670                         log_finish();
671                 }
672
673                 return NULL;
674         }
675
676         if (opt_verbosejni)
677                 printf("OK ]\n");
678
679         return handle;
680 }
681 #endif
682
683
684 /* native_library_close ********************************************************
685
686    Close the native library of the given handle.
687
688    IN:
689        handle ... handle of the open library
690
691 *******************************************************************************/
692
693 #if defined(ENABLE_DL)
694 void native_library_close(void* handle)
695 {
696         int result;
697
698         if (opt_verbosejni) {
699                 printf("[Unloading native library ");
700 /*              utf_display_printable_ascii(filename); */
701                 printf(" ... ");
702         }
703
704         /* Close the library. */
705
706         result = os_dlclose(handle);
707
708         if (result != 0) {
709                 if (opt_verbose) {
710                         log_start();
711                         log_print("native_library_close: os_dlclose failed: ");
712                         log_print(dlerror());
713                         log_finish();
714                 }
715         }
716 }
717 #endif
718
719
720 /* native_library_add **********************************************************
721
722    Adds an entry to the native library hashtable.
723
724 *******************************************************************************/
725
726 #if defined(ENABLE_DL)
727 void native_library_add(utf *filename, classloader_t *loader, void* handle)
728 {
729         hashtable_library_loader_entry *le;
730         hashtable_library_name_entry   *ne; /* library name                       */
731         u4   key;                           /* hashkey                            */
732         u4   slot;                          /* slot in hashtable                  */
733
734         LOCK_MONITOR_ENTER(hashtable_library->header);
735
736         /* normally addresses are aligned to 4, 8 or 16 bytes */
737
738         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
739         slot = key & (hashtable_library->size - 1);
740         le   = hashtable_library->ptr[slot];
741
742         /* search external hash chain for the entry */
743
744         while (le) {
745                 if (le->loader == loader)
746                         break;
747
748                 le = le->hashlink;                  /* next element in external chain */
749         }
750
751         /* no loader found? create a new entry */
752
753         if (le == NULL) {
754                 le = NEW(hashtable_library_loader_entry);
755
756                 le->loader   = loader;
757                 le->namelink = NULL;
758
759                 /* insert entry into hashtable */
760
761                 le->hashlink =
762                         (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
763                 hashtable_library->ptr[slot] = le;
764
765                 /* update number of hashtable-entries */
766
767                 hashtable_library->entries++;
768         }
769
770
771         /* search for library name */
772
773         ne = le->namelink;
774
775         while (ne) {
776                 if (ne->name == filename) {
777                         LOCK_MONITOR_EXIT(hashtable_library->header);
778
779                         return;
780                 }
781
782                 ne = ne->hashlink;                  /* next element in external chain */
783         }
784
785         /* not found? add the library name to the classloader */
786
787         ne = NEW(hashtable_library_name_entry);
788
789         ne->name   = filename;
790         ne->handle = handle;
791
792         /* insert entry into external chain */
793
794         ne->hashlink = le->namelink;
795         le->namelink = ne;
796
797         LOCK_MONITOR_EXIT(hashtable_library->header);
798 }
799 #endif
800
801
802 /* native_library_find *********************************************************
803
804    Find an entry in the native library hashtable.
805
806 *******************************************************************************/
807
808 #if defined(ENABLE_DL)
809 hashtable_library_name_entry *native_library_find(utf *filename,
810                                                                                                   classloader_t *loader)
811 {
812         hashtable_library_loader_entry *le;
813         hashtable_library_name_entry   *ne; /* library name                       */
814         u4   key;                           /* hashkey                            */
815         u4   slot;                          /* slot in hashtable                  */
816
817         /* normally addresses are aligned to 4, 8 or 16 bytes */
818
819         key  = ((u4) (ptrint) loader) >> 4;        /* align to 16-byte boundaries */
820         slot = key & (hashtable_library->size - 1);
821         le   = hashtable_library->ptr[slot];
822
823         /* search external hash chain for the entry */
824
825         while (le) {
826                 if (le->loader == loader)
827                         break;
828
829                 le = le->hashlink;                  /* next element in external chain */
830         }
831
832         /* no loader found? return NULL */
833
834         if (le == NULL)
835                 return NULL;
836
837         /* search for library name */
838
839         ne = le->namelink;
840
841         while (ne) {
842                 if (ne->name == filename)
843                         return ne;
844
845                 ne = ne->hashlink;                  /* next element in external chain */
846         }
847
848         /* return entry, if no entry was found, ne is NULL */
849
850         return ne;
851 }
852 #endif
853
854
855 /* native_library_load *********************************************************
856
857    Load a native library and initialize it, if possible.
858
859    IN:
860        name ... name of the library
861            cl ..... classloader which loads this library
862
863    RETURN:
864        1 ... library loaded successfully
865        0 ... error
866
867 *******************************************************************************/
868
869 int native_library_load(JNIEnv *env, utf *name, classloader_t *cl)
870 {
871 #if defined(ENABLE_DL)
872         void*   handle;
873 # if defined(ENABLE_JNI)
874         void*   onload;
875         int32_t version;
876 # endif
877
878         if (name == NULL) {
879                 exceptions_throw_nullpointerexception();
880                 return 0;
881         }
882
883         /* Is the library already loaded? */
884
885         if (native_library_find(name, cl) != NULL)
886                 return 1;
887
888         /* Open the library. */
889
890         handle = native_library_open(name);
891
892         if (handle == NULL)
893                 return 0;
894
895 # if defined(ENABLE_JNI)
896         /* Resolve JNI_OnLoad function. */
897
898         onload = os_dlsym(handle, "JNI_OnLoad");
899
900         if (onload != NULL) {
901                 JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
902                 JavaVM *vm;
903
904                 JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
905
906                 (*env)->GetJavaVM(env, &vm);
907
908                 version = JNI_OnLoad(vm, NULL);
909
910                 /* If the version is not 1.2 and not 1.4 the library cannot be
911                    loaded. */
912
913                 if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
914                         os_dlclose(handle);
915                         return 0;
916                 }
917         }
918 # endif
919
920         /* Insert the library name into the library hash. */
921
922         native_library_add(name, cl, handle);
923
924         return 1;
925 #else
926         vm_abort("native_library_load: not available");
927
928         /* Keep compiler happy. */
929
930         return 0;
931 #endif
932 }
933
934
935 /* native_new_and_init *********************************************************
936
937    Creates a new object on the heap and calls the initializer.
938    Returns the object pointer or NULL if memory is exhausted.
939                         
940 *******************************************************************************/
941
942 java_handle_t *native_new_and_init(classinfo *c)
943 {
944         methodinfo    *m;
945         java_handle_t *o;
946
947         if (c == NULL)
948                 vm_abort("native_new_and_init: c == NULL");
949
950         /* create object */
951
952         o = builtin_new(c);
953         
954         if (o == NULL)
955                 return NULL;
956
957         /* try to find the initializer */
958
959         m = class_findmethod(c, utf_init, utf_void__void);
960                                                       
961         /* ATTENTION: returning the object here is ok, since the class may
962        not have an initializer */
963
964         if (m == NULL)
965                 return o;
966
967         /* call initializer */
968
969         (void) vm_call_method(m, o);
970
971         return o;
972 }
973
974
975 java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
976 {
977         methodinfo    *m;
978         java_handle_t *o;
979
980         if (c == NULL)
981                 vm_abort("native_new_and_init_string: c == NULL");
982
983         /* create object */
984
985         o = builtin_new(c);
986
987         if (o == NULL)
988                 return NULL;
989
990         /* find initializer */
991
992         m = class_findmethod(c, utf_init, utf_java_lang_String__void);
993
994         /* initializer not found */
995
996         if (m == NULL)
997                 return NULL;
998
999         /* call initializer */
1000
1001         (void) vm_call_method(m, o, s);
1002
1003         return o;
1004 }
1005
1006
1007 /*
1008  * These are local overrides for various environment variables in Emacs.
1009  * Please do not remove this and leave it at the end of the file, where
1010  * Emacs will automagically detect them.
1011  * ---------------------------------------------------------------------
1012  * Local variables:
1013  * mode: c
1014  * indent-tabs-mode: t
1015  * c-basic-offset: 4
1016  * tab-width: 4
1017  * End:
1018  * vim:noexpandtab:sw=4:ts=4:
1019  */