* class_java_lang_NoSuchMethodError: Added.
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes: Edwin Steiner
30
31    $Id: exceptions.c 3612 2005-11-07 17:47:49Z twisti $
32
33 */
34
35
36 #include <string.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39
40 #include "config.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "native/include/java_lang_String.h"
45 #include "native/include/java_lang_Throwable.h"
46 #include "toolbox/logging.h"
47 #include "toolbox/util.h"
48 #include "vm/class.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/loader.h"
52 #include "vm/options.h"
53 #include "vm/stringlocal.h"
54 #include "vm/tables.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/jit.h"
57
58
59 /* for raising exceptions from native methods *********************************/
60
61 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
62 java_objectheader *_no_threads_exceptionptr = NULL;
63 #endif
64
65
66 /* init_system_exceptions ******************************************************
67
68    Load and link exceptions used in the system.
69
70 *******************************************************************************/
71
72 bool exceptions_init(void)
73 {
74         /* java/lang/Throwable */
75
76         if (!(class_java_lang_Throwable =
77                   load_class_bootstrap(utf_java_lang_Throwable)) ||
78                 !link_class(class_java_lang_Throwable))
79                 return false;
80
81
82         /* java/lang/VMThrowable */
83
84         if (!(class_java_lang_VMThrowable =
85                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
86                 !link_class(class_java_lang_VMThrowable))
87                 return false;
88
89
90         /* java/lang/Error */
91
92         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
93                 !link_class(class_java_lang_Error))
94                 return false;
95
96         /* java/lang/NoClassDefFoundError */
97
98         if (!(class_java_lang_NoClassDefFoundError =
99                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
100                 !link_class(class_java_lang_NoClassDefFoundError))
101                 return false;
102
103         /* java/lang/OutOfMemoryError */
104
105         if (!(class_java_lang_OutOfMemoryError =
106                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
107                 !link_class(class_java_lang_OutOfMemoryError))
108                 return false;
109
110
111         /* java/lang/Exception */
112
113         if (!(class_java_lang_Exception =
114                   load_class_bootstrap(utf_java_lang_Exception)) ||
115                 !link_class(class_java_lang_Exception))
116                 return false;
117
118         /* java/lang/ClassNotFoundException */
119
120         if (!(class_java_lang_ClassNotFoundException =
121                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
122                 !link_class(class_java_lang_ClassNotFoundException))
123                 return false;
124
125         /* java/lang/IllegalArgumentException */
126
127         if (!(class_java_lang_IllegalArgumentException =
128                   load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
129                 !link_class(class_java_lang_IllegalArgumentException))
130                 return false;
131
132         /* java/lang/IllegalMonitorStateException */
133
134         if (!(class_java_lang_IllegalMonitorStateException =
135                   load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
136                 !link_class(class_java_lang_IllegalMonitorStateException))
137                 return false;
138
139         /* java/lang/NullPointerException */
140
141         if (!(class_java_lang_NullPointerException =
142                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
143                 !link_class(class_java_lang_NullPointerException))
144                 return false;
145
146
147         return true;
148 }
149
150
151 static void throw_exception_exit_intern(bool doexit)
152 {
153         java_objectheader *xptr;
154         classinfo *c;
155         methodinfo *pss;
156
157         xptr = *exceptionptr;
158
159         if (xptr) {
160                 /* clear exception, because we are calling jit code again */
161                 *exceptionptr = NULL;
162
163                 c = xptr->vftbl->class;
164
165                 pss = class_resolveclassmethod(c,
166                                                                            utf_printStackTrace,
167                                                                            utf_void__void,
168                                                                            class_java_lang_Object,
169                                                                            false);
170
171                 /* print the stacktrace */
172                 if (pss) {
173                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
174
175                         /* This normally means, we are EXTREMLY out of memory or have a   */
176                         /* serious problem while printStackTrace. But may be another      */
177                         /* exception, so print it.                                        */
178
179                         if (*exceptionptr) {
180                                 java_lang_Throwable *t;
181
182                                 t = (java_lang_Throwable *) *exceptionptr;
183
184                                 fprintf(stderr, "Exception while printStackTrace(): ");
185                                 utf_fprint_classname(stderr, t->header.vftbl->class->name);
186
187                                 if (t->detailMessage) {
188                                         char *buf;
189
190                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
191                                         fprintf(stderr, ": %s", buf);
192                                         MFREE(buf, char, strlen(buf));
193                                 }
194                                         
195                                 fprintf(stderr, "\n");
196                         }
197
198                 } else {
199                         utf_fprint_classname(stderr, c->name);
200                         fprintf(stderr, ": printStackTrace()V not found!\n");
201                 }
202
203                 fflush(stderr);
204
205                 /* good bye! */
206
207                 if (doexit)
208                         exit(1);
209         }
210 }
211
212
213 void throw_exception(void)
214 {
215         throw_exception_exit_intern(false);
216 }
217
218
219 void throw_exception_exit(void)
220 {
221         throw_exception_exit_intern(true);
222 }
223
224
225 void throw_main_exception(void)
226 {
227         fprintf(stderr, "Exception in thread \"main\" ");
228         fflush(stderr);
229
230         throw_exception_exit_intern(false);
231 }
232
233
234 void throw_main_exception_exit(void)
235 {
236         fprintf(stderr, "Exception in thread \"main\" ");
237         fflush(stderr);
238
239         throw_exception_exit_intern(true);
240 }
241
242
243 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
244 {
245         s4 i;
246         char *tmp;
247         s4 len;
248         va_list ap;
249
250         len = strlen(exception);
251         tmp = MNEW(char, len + 1);
252         strncpy(tmp, exception, len);
253         tmp[len] = '\0';
254
255         /* convert to classname */
256
257         for (i = len - 1; i >= 0; i--)
258                 if (tmp[i] == '/') tmp[i] = '.';
259
260         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
261
262         MFREE(tmp, char, len);
263
264         if (strlen(message) > 0) {
265                 fprintf(stderr, ": ");
266
267                 va_start(ap, message);
268                 vfprintf(stderr, message, ap);
269                 va_end(ap);
270         }
271
272         fprintf(stderr, "\n");
273         fflush(stderr);
274
275         /* good bye! */
276
277         exit(1);
278 }
279
280
281 /* exceptions_throw_outofmemory_exit *******************************************
282
283    Just print an: java.lang.InternalError: Out of memory
284
285 *******************************************************************************/
286
287 void exceptions_throw_outofmemory_exit(void)
288 {
289         throw_cacao_exception_exit(string_java_lang_InternalError,
290                                                            "Out of memory");
291 }
292
293
294 /* new_exception ***************************************************************
295
296    Creates an exception object with the given name and initalizes it.
297
298 *******************************************************************************/
299
300 java_objectheader *new_exception(const char *classname)
301 {
302         java_objectheader *o;
303         classinfo         *c;
304
305         if (!(c = load_class_bootstrap(utf_new_char(classname))))
306                 return *exceptionptr;
307
308         o = native_new_and_init(c);
309
310         if (!o)
311                 return *exceptionptr;
312
313         return o;
314 }
315
316
317 /* new_exception_message *******************************************************
318
319    Creates an exception object with the given name and initalizes it
320    with the given char message.
321
322 *******************************************************************************/
323
324 java_objectheader *new_exception_message(const char *classname,
325                                                                                  const char *message)
326 {
327         java_objectheader *o;
328         classinfo         *c;
329    
330         if (!(c = load_class_bootstrap(utf_new_char(classname))))
331                 return *exceptionptr;
332
333         o = native_new_and_init_string(c, javastring_new_char(message));
334
335         if (!o)
336                 return *exceptionptr;
337
338         return o;
339 }
340
341
342 /* new_exception_throwable *****************************************************
343
344    Creates an exception object with the given name and initalizes it
345    with the given java/lang/Throwable exception.
346
347 *******************************************************************************/
348
349 java_objectheader *new_exception_throwable(const char *classname,
350                                                                                    java_lang_Throwable *throwable)
351 {
352         java_objectheader *o;
353         classinfo         *c;
354    
355         if (!(c = load_class_bootstrap(utf_new_char(classname))))
356                 return *exceptionptr;
357
358         o = native_new_and_init_throwable(c, throwable);
359
360         if (!o)
361                 return *exceptionptr;
362
363         return o;
364 }
365
366
367 /* new_exception_utfmessage ****************************************************
368
369    Creates an exception object with the given name and initalizes it
370    with the given utf message.
371
372 *******************************************************************************/
373
374 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
375 {
376         java_objectheader *o;
377         classinfo         *c;
378    
379         if (!(c = load_class_bootstrap(utf_new_char(classname))))
380                 return *exceptionptr;
381
382         o = native_new_and_init_string(c, javastring_new(message));
383
384         if (!o)
385                 return *exceptionptr;
386
387         return o;
388 }
389
390
391 /* new_exception_javastring ****************************************************
392
393    Creates an exception object with the given name and initalizes it
394    with the given java/lang/String message.
395
396 *******************************************************************************/
397
398 java_objectheader *new_exception_javastring(const char *classname,
399                                                                                         java_lang_String *message)
400 {
401         java_objectheader *o;
402         classinfo         *c;
403    
404         if (!(c = load_class_bootstrap(utf_new_char(classname))))
405                 return *exceptionptr;
406
407         o = native_new_and_init_string(c, message);
408
409         if (!o)
410                 return *exceptionptr;
411
412         return o;
413 }
414
415
416 /* new_exception_int ***********************************************************
417
418    Creates an exception object with the given name and initalizes it
419    with the given int value.
420
421 *******************************************************************************/
422
423 java_objectheader *new_exception_int(const char *classname, s4 i)
424 {
425         java_objectheader *o;
426         classinfo         *c;
427    
428         if (!(c = load_class_bootstrap(utf_new_char(classname))))
429                 return *exceptionptr;
430
431         o = native_new_and_init_int(c, i);
432
433         if (!o)
434                 return *exceptionptr;
435
436         return o;
437 }
438
439
440 /* new_classformaterror ********************************************************
441
442    generates a java.lang.ClassFormatError for the classloader
443
444 *******************************************************************************/
445
446 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
447 {
448         java_objectheader *o;
449         char              *msg;
450         s4                 msglen;
451         va_list            ap;
452
453         /* calculate message length */
454
455         msglen = 0;
456
457         if (c)
458                 msglen += utf_strlen(c->name) + strlen(" (");
459
460         va_start(ap, message);
461         msglen += get_variable_message_length(message, ap);
462         va_end(ap);
463
464         if (c)
465                 msglen += strlen(")");
466
467         msglen += strlen("0");
468
469         /* allocate a buffer */
470
471         msg = MNEW(char, msglen);
472
473         /* print message into allocated buffer */
474
475         if (c) {
476                 utf_sprint_classname(msg, c->name);
477                 strcat(msg, " (");
478         }
479
480         va_start(ap, message);
481         vsprintf(msg + strlen(msg), message, ap);
482         va_end(ap);
483
484         if (c)
485                 strcat(msg, ")");
486
487         o = new_exception_message(string_java_lang_ClassFormatError, msg);
488
489         MFREE(msg, char, msglen);
490
491         return o;
492 }
493
494
495 /* new_classnotfoundexception **************************************************
496
497    Generates a java.lang.ClassNotFoundException for the classloader.
498
499 *******************************************************************************/
500
501 java_objectheader *new_classnotfoundexception(utf *name)
502 {
503         java_objectheader *o;
504
505         o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
506                                                                    javastring_new(name));
507
508         if (!o)
509                 return *exceptionptr;
510
511         return o;
512 }
513
514
515 /* new_noclassdeffounderror ****************************************************
516
517    Generates a java.lang.NoClassDefFoundError
518
519 *******************************************************************************/
520
521 java_objectheader *new_noclassdeffounderror(utf *name)
522 {
523         java_objectheader *o;
524
525         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
526                                                                    javastring_new(name));
527
528         if (!o)
529                 return *exceptionptr;
530
531         return o;
532 }
533
534
535 /* classnotfoundexception_to_noclassdeffounderror ******************************
536
537    Check the *exceptionptr for a ClassNotFoundException. If it is one,
538    convert it to a NoClassDefFoundError.
539
540 *******************************************************************************/
541
542 void classnotfoundexception_to_noclassdeffounderror(void)
543 {
544         java_objectheader *xptr;
545         java_objectheader *cause;
546
547         /* get the cause */
548
549         cause = *exceptionptr;
550
551         /* convert ClassNotFoundException's to NoClassDefFoundError's */
552
553         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
554                 /* clear exception, because we are calling jit code again */
555
556                 *exceptionptr = NULL;
557
558                 /* create new error */
559
560                 xptr =
561                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
562                                         ((java_lang_Throwable *) cause)->detailMessage);
563
564                 /* we had an exception while creating the error */
565
566                 if (*exceptionptr)
567                         return;
568
569                 /* set new exception */
570
571                 *exceptionptr = xptr;
572         }
573 }
574
575
576 /* new_internalerror ***********************************************************
577
578    Generates a java.lang.InternalError for the VM.
579
580 *******************************************************************************/
581
582 java_objectheader *new_internalerror(const char *message, ...)
583 {
584         java_objectheader *o;
585         va_list            ap;
586         char              *msg;
587         s4                 msglen;
588
589         /* calculate exception message length */
590
591         va_start(ap, message);
592         msglen = get_variable_message_length(message, ap);
593         va_end(ap);
594
595         /* allocate memory */
596
597         msg = MNEW(char, msglen);
598
599         /* generate message */
600
601         va_start(ap, message);
602         vsprintf(msg, message, ap);
603         va_end(ap);
604
605         /* create exception object */
606
607         o = new_exception_message(string_java_lang_InternalError, msg);
608
609         /* free memory */
610
611         MFREE(msg, char, msglen);
612
613         return o;
614 }
615
616
617 /* new_unsupportedclassversionerror ********************************************
618
619    generates a java.lang.UnsupportedClassVersionError for the classloader
620
621 *******************************************************************************/
622
623 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
624 {
625         java_objectheader *o;
626         va_list            ap;
627         char              *msg;
628     s4                 msglen;
629
630         /* calculate exception message length */
631
632         msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
633
634         va_start(ap, message);
635         msglen += get_variable_message_length(message, ap);
636         va_end(ap);
637
638         /* allocate memory */
639
640         msg = MNEW(char, msglen);
641
642         /* generate message */
643
644         utf_sprint_classname(msg, c->name);
645         strcat(msg, " (");
646
647         va_start(ap, message);
648         vsprintf(msg + strlen(msg), message, ap);
649         va_end(ap);
650
651         strcat(msg, ")");
652
653         /* create exception object */
654
655         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
656                                                           msg);
657
658         /* free memory */
659
660         MFREE(msg, char, msglen);
661
662         return o;
663 }
664
665
666 /* new_verifyerror *************************************************************
667
668    generates a java.lang.VerifyError for the jit compiler
669
670 *******************************************************************************/
671
672 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
673 {
674         java_objectheader *o;
675         va_list            ap;
676         char              *msg;
677         s4                 msglen;
678
679         useinlining = false; /* at least until sure inlining works with exceptions*/
680
681         /* calculate exception message length */
682
683         msglen = 0;
684
685         if (m)
686                 msglen = strlen("(class: ") + utf_strlen(m->class->name) +
687                         strlen(", method: ") + utf_strlen(m->name) +
688                         strlen(" signature: ") + utf_strlen(m->descriptor) +
689                         strlen(") ") + strlen("0");
690
691         va_start(ap, message);
692         msglen += get_variable_message_length(message, ap);
693         va_end(ap);
694
695         /* allocate memory */
696
697         msg = MNEW(char, msglen);
698
699         /* generate message */
700
701         if (m) {
702                 strcpy(msg, "(class: ");
703                 utf_strcat(msg, m->class->name);
704                 strcat(msg, ", method: ");
705                 utf_strcat(msg, m->name);
706                 strcat(msg, " signature: ");
707                 utf_strcat(msg, m->descriptor);
708                 strcat(msg, ") ");
709         }
710
711         va_start(ap, message);
712         vsprintf(msg + strlen(msg), message, ap);
713         va_end(ap);
714
715         /* create exception object */
716
717         o = new_exception_message(string_java_lang_VerifyError, msg);
718
719         /* free memory */
720
721         MFREE(msg, char, msglen);
722
723         return o;
724 }
725
726
727 /* new_arithmeticexception *****************************************************
728
729    Generates a java.lang.ArithmeticException for the jit compiler.
730
731 *******************************************************************************/
732
733 java_objectheader *new_arithmeticexception(void)
734 {
735         java_objectheader *e;
736
737         e = new_exception_message(string_java_lang_ArithmeticException,
738                                                           string_java_lang_ArithmeticException_message);
739
740         if (!e)
741                 return *exceptionptr;
742
743         return e;
744 }
745
746
747 /* new_arrayindexoutofboundsexception ******************************************
748
749    Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
750    compiler.
751
752 *******************************************************************************/
753
754 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
755 {
756         java_objectheader *e;
757         methodinfo *m;
758         java_lang_String *s;
759
760         /* convert the index into a String, like Sun does */
761
762         m = class_resolveclassmethod(class_java_lang_String,
763                                                                  utf_new_char("valueOf"),
764                                                                  utf_new_char("(I)Ljava/lang/String;"),
765                                                                  class_java_lang_Object,
766                                                                  true);
767
768         if (!m)
769                 return *exceptionptr;
770
771         s = (java_lang_String *) asm_calljavafunction(m,
772                                                                                                   (void *) (ptrint) index,
773                                                                                                   NULL,
774                                                                                                   NULL,
775                                                                                                   NULL);
776
777         if (!s)
778                 return *exceptionptr;
779
780         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
781                                                                  s);
782
783         if (!e)
784                 return *exceptionptr;
785
786         return e;
787 }
788
789
790 /* new_arraystoreexception *****************************************************
791
792    generates a java.lang.ArrayStoreException for the jit compiler
793
794 *******************************************************************************/
795
796 java_objectheader *new_arraystoreexception(void)
797 {
798         java_objectheader *e;
799
800         e = new_exception(string_java_lang_ArrayStoreException);
801 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
802
803         if (!e)
804                 return *exceptionptr;
805
806         return e;
807 }
808
809
810 /* new_classcastexception ******************************************************
811
812    generates a java.lang.ClassCastException for the jit compiler
813
814 *******************************************************************************/
815
816 java_objectheader *new_classcastexception(void)
817 {
818         java_objectheader *e;
819
820         e = new_exception(string_java_lang_ClassCastException);
821
822         if (!e)
823                 return *exceptionptr;
824
825         return e;
826 }
827
828
829 /* new_illegalargumentexception ************************************************
830
831    Generates a java.lang.IllegalArgumentException for the VM system.
832
833 *******************************************************************************/
834
835 java_objectheader *new_illegalargumentexception(void)
836 {
837         java_objectheader *e;
838
839         if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException)))
840                 return *exceptionptr;
841
842         return e;
843 }
844
845
846 /* new_illegalmonitorstateexception ********************************************
847
848    Generates a java.lang.IllegalMonitorStateException for the VM
849    thread system.
850
851 *******************************************************************************/
852
853 java_objectheader *new_illegalmonitorstateexception(void)
854 {
855         java_objectheader *e;
856
857         if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException)))
858                 return *exceptionptr;
859
860         return e;
861 }
862
863
864 /* new_negativearraysizeexception **********************************************
865
866    generates a java.lang.NegativeArraySizeException for the jit compiler
867
868 *******************************************************************************/
869
870 java_objectheader *new_negativearraysizeexception(void)
871 {
872         java_objectheader *e;
873
874         e = new_exception(string_java_lang_NegativeArraySizeException);
875
876         if (!e)
877                 return *exceptionptr;
878
879         return e;
880 }
881
882
883 /* new_nullpointerexception ****************************************************
884
885    generates a java.lang.NullPointerException for the jit compiler
886
887 *******************************************************************************/
888
889 java_objectheader *new_nullpointerexception(void)
890 {
891         java_objectheader *e;
892
893         e = native_new_and_init(class_java_lang_NullPointerException);
894
895         if (!e)
896                 return *exceptionptr;
897
898         return e;
899 }
900
901
902 /*
903  * These are local overrides for various environment variables in Emacs.
904  * Please do not remove this and leave it at the end of the file, where
905  * Emacs will automagically detect them.
906  * ---------------------------------------------------------------------
907  * Local variables:
908  * mode: c
909  * indent-tabs-mode: t
910  * c-basic-offset: 4
911  * tab-width: 4
912  * End:
913  */