201 // returns first instance method |
201 // returns first instance method |
202 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
202 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
203 Method* result_oop = klass->uncached_lookup_method(name, signature); |
203 Method* result_oop = klass->uncached_lookup_method(name, signature); |
204 result = methodHandle(THREAD, result_oop); |
204 result = methodHandle(THREAD, result_oop); |
205 while (!result.is_null() && result->is_static()) { |
205 while (!result.is_null() && result->is_static()) { |
206 klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super()); |
206 klass = KlassHandle(THREAD, result->method_holder()->super()); |
207 result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); |
207 result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); |
208 } |
208 } |
209 } |
209 } |
210 |
210 |
211 |
211 |
426 |
426 |
427 if (resolved_method.is_null()) { |
427 if (resolved_method.is_null()) { |
428 // 3. method lookup failed |
428 // 3. method lookup failed |
429 ResourceMark rm(THREAD); |
429 ResourceMark rm(THREAD); |
430 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), |
430 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), |
431 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
431 Method::name_and_sig_as_C_string(resolved_klass(), |
432 method_name, |
432 method_name, |
433 method_signature), |
433 method_signature), |
434 nested_exception); |
434 nested_exception); |
435 } |
435 } |
436 } |
436 } |
446 |
446 |
447 // 5. check if method is concrete |
447 // 5. check if method is concrete |
448 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { |
448 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { |
449 ResourceMark rm(THREAD); |
449 ResourceMark rm(THREAD); |
450 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
450 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
451 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
451 Method::name_and_sig_as_C_string(resolved_klass(), |
452 method_name, |
452 method_name, |
453 method_signature)); |
453 method_signature)); |
454 } |
454 } |
455 |
455 |
456 // 6. access checks, access checking may be turned off when calling from within the VM. |
456 // 6. access checks, access checking may be turned off when calling from within the VM. |
475 if (failed_type_name != NULL) { |
475 if (failed_type_name != NULL) { |
476 const char* msg = "loader constraint violation: when resolving method" |
476 const char* msg = "loader constraint violation: when resolving method" |
477 " \"%s\" the class loader (instance of %s) of the current class, %s," |
477 " \"%s\" the class loader (instance of %s) of the current class, %s," |
478 " and the class loader (instance of %s) for resolved class, %s, have" |
478 " and the class loader (instance of %s) for resolved class, %s, have" |
479 " different Class objects for the type %s used in the signature"; |
479 " different Class objects for the type %s used in the signature"; |
480 char* sig = Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature); |
480 char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); |
481 const char* loader1 = SystemDictionary::loader_name(loader()); |
481 const char* loader1 = SystemDictionary::loader_name(loader()); |
482 char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); |
482 char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); |
483 const char* loader2 = SystemDictionary::loader_name(class_loader()); |
483 const char* loader2 = SystemDictionary::loader_name(class_loader()); |
484 char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); |
484 char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); |
485 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + |
485 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + |
503 |
503 |
504 // check if klass is interface |
504 // check if klass is interface |
505 if (!resolved_klass->is_interface()) { |
505 if (!resolved_klass->is_interface()) { |
506 ResourceMark rm(THREAD); |
506 ResourceMark rm(THREAD); |
507 char buf[200]; |
507 char buf[200]; |
508 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", Klass::cast(resolved_klass())->external_name()); |
508 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); |
509 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
509 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
510 } |
510 } |
511 |
511 |
512 // lookup method in this interface or its super, java.lang.Object |
512 // lookup method in this interface or its super, java.lang.Object |
513 lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
513 lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
517 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
517 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
518 if (resolved_method.is_null()) { |
518 if (resolved_method.is_null()) { |
519 // no method found |
519 // no method found |
520 ResourceMark rm(THREAD); |
520 ResourceMark rm(THREAD); |
521 THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), |
521 THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), |
522 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
522 Method::name_and_sig_as_C_string(resolved_klass(), |
523 method_name, |
523 method_name, |
524 method_signature)); |
524 method_signature)); |
525 } |
525 } |
526 } |
526 } |
527 |
527 |
538 const char* msg = "loader constraint violation: when resolving " |
538 const char* msg = "loader constraint violation: when resolving " |
539 "interface method \"%s\" the class loader (instance of %s) of the " |
539 "interface method \"%s\" the class loader (instance of %s) of the " |
540 "current class, %s, and the class loader (instance of %s) for " |
540 "current class, %s, and the class loader (instance of %s) for " |
541 "resolved class, %s, have different Class objects for the type %s " |
541 "resolved class, %s, have different Class objects for the type %s " |
542 "used in the signature"; |
542 "used in the signature"; |
543 char* sig = Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature); |
543 char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); |
544 const char* loader1 = SystemDictionary::loader_name(loader()); |
544 const char* loader1 = SystemDictionary::loader_name(loader()); |
545 char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); |
545 char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); |
546 const char* loader2 = SystemDictionary::loader_name(class_loader()); |
546 const char* loader2 = SystemDictionary::loader_name(class_loader()); |
547 char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); |
547 char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); |
548 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + |
548 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + |
625 |
625 |
626 // check for errors |
626 // check for errors |
627 if (is_static != fd.is_static()) { |
627 if (is_static != fd.is_static()) { |
628 ResourceMark rm(THREAD); |
628 ResourceMark rm(THREAD); |
629 char msg[200]; |
629 char msg[200]; |
630 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", Klass::cast(resolved_klass())->external_name(), fd.name()->as_C_string()); |
630 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string()); |
631 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); |
631 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); |
632 } |
632 } |
633 |
633 |
634 // Final fields can only be accessed from its own class. |
634 // Final fields can only be accessed from its own class. |
635 if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) { |
635 if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) { |
699 void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, |
699 void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, |
700 Symbol* method_signature, KlassHandle current_klass, |
700 Symbol* method_signature, KlassHandle current_klass, |
701 bool check_access, bool initialize_class, TRAPS) { |
701 bool check_access, bool initialize_class, TRAPS) { |
702 methodHandle resolved_method; |
702 methodHandle resolved_method; |
703 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
703 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
704 resolved_klass = KlassHandle(THREAD, Klass::cast(resolved_method->method_holder())); |
704 resolved_klass = KlassHandle(THREAD, resolved_method->method_holder()); |
705 |
705 |
706 // Initialize klass (this should only happen if everything is ok) |
706 // Initialize klass (this should only happen if everything is ok) |
707 if (initialize_class && resolved_klass->should_be_initialized()) { |
707 if (initialize_class && resolved_klass->should_be_initialized()) { |
708 resolved_klass->initialize(CHECK); |
708 resolved_klass->initialize(CHECK); |
709 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
709 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
723 |
723 |
724 // check if static |
724 // check if static |
725 if (!resolved_method->is_static()) { |
725 if (!resolved_method->is_static()) { |
726 ResourceMark rm(THREAD); |
726 ResourceMark rm(THREAD); |
727 char buf[200]; |
727 char buf[200]; |
728 jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
728 jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
729 resolved_method->name(), |
729 resolved_method->name(), |
730 resolved_method->signature())); |
730 resolved_method->signature())); |
731 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
731 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
732 } |
732 } |
733 } |
733 } |
787 if (resolved_method->is_static()) { |
787 if (resolved_method->is_static()) { |
788 ResourceMark rm(THREAD); |
788 ResourceMark rm(THREAD); |
789 char buf[200]; |
789 char buf[200]; |
790 jio_snprintf(buf, sizeof(buf), |
790 jio_snprintf(buf, sizeof(buf), |
791 "Expecting non-static method %s", |
791 "Expecting non-static method %s", |
792 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
792 Method::name_and_sig_as_C_string(resolved_klass(), |
793 resolved_method->name(), |
793 resolved_method->name(), |
794 resolved_method->signature())); |
794 resolved_method->signature())); |
795 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
795 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
796 } |
796 } |
797 } |
797 } |
827 resolved_method->signature(), CHECK); |
827 resolved_method->signature(), CHECK); |
828 // check if found |
828 // check if found |
829 if (sel_method.is_null()) { |
829 if (sel_method.is_null()) { |
830 ResourceMark rm(THREAD); |
830 ResourceMark rm(THREAD); |
831 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
831 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
832 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
832 Method::name_and_sig_as_C_string(resolved_klass(), |
833 resolved_method->name(), |
833 resolved_method->name(), |
834 resolved_method->signature())); |
834 resolved_method->signature())); |
835 } |
835 } |
836 } |
836 } |
837 } |
837 } |
838 |
838 |
839 // check if not static |
839 // check if not static |
840 if (sel_method->is_static()) { |
840 if (sel_method->is_static()) { |
841 ResourceMark rm(THREAD); |
841 ResourceMark rm(THREAD); |
842 char buf[200]; |
842 char buf[200]; |
843 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
843 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
844 resolved_method->name(), |
844 resolved_method->name(), |
845 resolved_method->signature())); |
845 resolved_method->signature())); |
846 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
846 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
847 } |
847 } |
848 |
848 |
849 // check if abstract |
849 // check if abstract |
850 if (sel_method->is_abstract()) { |
850 if (sel_method->is_abstract()) { |
851 ResourceMark rm(THREAD); |
851 ResourceMark rm(THREAD); |
852 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
852 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
853 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
853 Method::name_and_sig_as_C_string(resolved_klass(), |
854 sel_method->name(), |
854 sel_method->name(), |
855 sel_method->signature())); |
855 sel_method->signature())); |
856 } |
856 } |
857 |
857 |
858 // setup result |
858 // setup result |
879 |
879 |
880 // check if not static |
880 // check if not static |
881 if (resolved_method->is_static()) { |
881 if (resolved_method->is_static()) { |
882 ResourceMark rm(THREAD); |
882 ResourceMark rm(THREAD); |
883 char buf[200]; |
883 char buf[200]; |
884 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
884 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
885 resolved_method->name(), |
885 resolved_method->name(), |
886 resolved_method->signature())); |
886 resolved_method->signature())); |
887 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
887 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
888 } |
888 } |
889 } |
889 } |
948 |
948 |
949 // check if method exists |
949 // check if method exists |
950 if (selected_method.is_null()) { |
950 if (selected_method.is_null()) { |
951 ResourceMark rm(THREAD); |
951 ResourceMark rm(THREAD); |
952 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
952 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
953 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
953 Method::name_and_sig_as_C_string(resolved_klass(), |
954 resolved_method->name(), |
954 resolved_method->name(), |
955 resolved_method->signature())); |
955 resolved_method->signature())); |
956 } |
956 } |
957 |
957 |
958 // check if abstract |
958 // check if abstract |
959 if (check_null_and_abstract && selected_method->is_abstract()) { |
959 if (check_null_and_abstract && selected_method->is_abstract()) { |
960 ResourceMark rm(THREAD); |
960 ResourceMark rm(THREAD); |
961 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
961 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
962 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
962 Method::name_and_sig_as_C_string(resolved_klass(), |
963 selected_method->name(), |
963 selected_method->name(), |
964 selected_method->signature())); |
964 selected_method->signature())); |
965 } |
965 } |
966 |
966 |
967 // setup result |
967 // setup result |
997 // check if receiver klass implements the resolved interface |
997 // check if receiver klass implements the resolved interface |
998 if (!recv_klass->is_subtype_of(resolved_klass())) { |
998 if (!recv_klass->is_subtype_of(resolved_klass())) { |
999 ResourceMark rm(THREAD); |
999 ResourceMark rm(THREAD); |
1000 char buf[200]; |
1000 char buf[200]; |
1001 jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", |
1001 jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", |
1002 (Klass::cast(recv_klass()))->external_name(), |
1002 recv_klass()->external_name(), |
1003 (Klass::cast(resolved_klass()))->external_name()); |
1003 resolved_klass()->external_name()); |
1004 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1004 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1005 } |
1005 } |
1006 // do lookup based on receiver klass |
1006 // do lookup based on receiver klass |
1007 methodHandle sel_method; |
1007 methodHandle sel_method; |
1008 lookup_instance_method_in_klasses(sel_method, recv_klass, |
1008 lookup_instance_method_in_klasses(sel_method, recv_klass, |
1010 resolved_method->signature(), CHECK); |
1010 resolved_method->signature(), CHECK); |
1011 // check if method exists |
1011 // check if method exists |
1012 if (sel_method.is_null()) { |
1012 if (sel_method.is_null()) { |
1013 ResourceMark rm(THREAD); |
1013 ResourceMark rm(THREAD); |
1014 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1014 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1015 Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), |
1015 Method::name_and_sig_as_C_string(recv_klass(), |
1016 resolved_method->name(), |
1016 resolved_method->name(), |
1017 resolved_method->signature())); |
1017 resolved_method->signature())); |
1018 } |
1018 } |
1019 // check if public |
1019 // check if public |
1020 if (!sel_method->is_public()) { |
1020 if (!sel_method->is_public()) { |
1021 ResourceMark rm(THREAD); |
1021 ResourceMark rm(THREAD); |
1022 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1022 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1023 Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), |
1023 Method::name_and_sig_as_C_string(recv_klass(), |
1024 sel_method->name(), |
1024 sel_method->name(), |
1025 sel_method->signature())); |
1025 sel_method->signature())); |
1026 } |
1026 } |
1027 // check if abstract |
1027 // check if abstract |
1028 if (check_null_and_abstract && sel_method->is_abstract()) { |
1028 if (check_null_and_abstract && sel_method->is_abstract()) { |
1029 ResourceMark rm(THREAD); |
1029 ResourceMark rm(THREAD); |
1030 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1030 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1031 Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), |
1031 Method::name_and_sig_as_C_string(recv_klass(), |
1032 sel_method->name(), |
1032 sel_method->name(), |
1033 sel_method->signature())); |
1033 sel_method->signature())); |
1034 } |
1034 } |
1035 // setup result |
1035 // setup result |
1036 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK); |
1036 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK); |