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