src/share/vm/interpreter/linkResolver.cpp

changeset 5786
36b97be47bde
parent 5784
190899198332
child 5848
ac9cb1d5a202
     1.1 --- a/src/share/vm/interpreter/linkResolver.cpp	Fri Sep 27 10:08:56 2013 -0400
     1.2 +++ b/src/share/vm/interpreter/linkResolver.cpp	Tue Oct 01 08:10:42 2013 -0400
     1.3 @@ -1,5 +1,4 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7   *
     1.8   * This code is free software; you can redistribute it and/or modify it
     1.9 @@ -573,6 +572,16 @@
    1.10    }
    1.11  
    1.12    if (check_access) {
    1.13 +    // JDK8 adds non-public interface methods, and accessability check requirement
    1.14 +    assert(current_klass.not_null() , "current_klass should not be null");
    1.15 +
    1.16 +    // check if method can be accessed by the referring class
    1.17 +    check_method_accessability(current_klass,
    1.18 +                               resolved_klass,
    1.19 +                               KlassHandle(THREAD, resolved_method->method_holder()),
    1.20 +                               resolved_method,
    1.21 +                               CHECK);
    1.22 +
    1.23      HandleMark hm(THREAD);
    1.24      Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
    1.25      Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
    1.26 @@ -604,6 +613,20 @@
    1.27        }
    1.28      }
    1.29    }
    1.30 +
    1.31 +  if (TraceItables && Verbose) {
    1.32 +    ResourceMark rm(THREAD);
    1.33 +    tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
    1.34 +                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
    1.35 +                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
    1.36 +                   Method::name_and_sig_as_C_string(resolved_klass(),
    1.37 +                                                    resolved_method->name(),
    1.38 +                                                    resolved_method->signature()),
    1.39 +                   resolved_method->method_holder()->internal_name()
    1.40 +                  );
    1.41 +    resolved_method->access_flags().print_on(tty);
    1.42 +    tty->cr();
    1.43 +  }
    1.44  }
    1.45  
    1.46  //------------------------------------------------------------------------------------------------------------------------
    1.47 @@ -795,26 +818,12 @@
    1.48                                                     Symbol* method_name, Symbol* method_signature,
    1.49                                                     KlassHandle current_klass, bool check_access, TRAPS) {
    1.50  
    1.51 -  if (resolved_klass->is_interface() && current_klass() != NULL) {
    1.52 -    // If the target class is a direct interface, treat this as a "super"
    1.53 -    // default call.
    1.54 -    //
    1.55 -    // If the current method is an overpass that happens to call a direct
    1.56 -    // super-interface's method, then we'll end up rerunning the default method
    1.57 -    // analysis even though we don't need to, but that's ok since it will end
    1.58 -    // up with the same answer.
    1.59 -    InstanceKlass* ik = InstanceKlass::cast(current_klass());
    1.60 -    Array<Klass*>* interfaces = ik->local_interfaces();
    1.61 -    int num_interfaces = interfaces->length();
    1.62 -    for (int index = 0; index < num_interfaces; index++) {
    1.63 -      if (interfaces->at(index) == resolved_klass()) {
    1.64 -        Method* method = DefaultMethods::find_super_default(current_klass(),
    1.65 -            resolved_klass(), method_name, method_signature, CHECK);
    1.66 -        resolved_method = methodHandle(THREAD, method);
    1.67 -        return;
    1.68 -      }
    1.69 -    }
    1.70 -  }
    1.71 +  // Invokespecial is called for multiple special reasons:
    1.72 +  // <init>
    1.73 +  // local private method invocation, for classes and interfaces
    1.74 +  // superclass.method, which can also resolve to a default method
    1.75 +  // and the selected method is recalculated relative to the direct superclass
    1.76 +  // superinterface.method, which explicitly does not check shadowing
    1.77  
    1.78    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
    1.79  
    1.80 @@ -844,6 +853,26 @@
    1.81                                                           resolved_method->signature()));
    1.82      THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
    1.83    }
    1.84 +  if (TraceItables && Verbose) {
    1.85 +    ResourceMark rm(THREAD);
    1.86 +    tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
    1.87 +                (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
    1.88 +                (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
    1.89 +                Method::name_and_sig_as_C_string(resolved_klass(),
    1.90 +                                                 resolved_method->name(),
    1.91 +                                                 resolved_method->signature()),
    1.92 +                resolved_method->method_holder()->internal_name()
    1.93 +               );
    1.94 +    resolved_method->access_flags().print_on(tty);
    1.95 +    if (resolved_method->method_holder()->is_interface() &&
    1.96 +        !resolved_method->is_abstract()) {
    1.97 +      tty->print("default");
    1.98 +    }
    1.99 +    if (resolved_method->is_overpass()) {
   1.100 +      tty->print("overpass");
   1.101 +    }
   1.102 +    tty->cr();
   1.103 +  }
   1.104  }
   1.105  
   1.106  // throws runtime exceptions
   1.107 @@ -851,23 +880,24 @@
   1.108                                                    KlassHandle current_klass, bool check_access, TRAPS) {
   1.109  
   1.110    // resolved method is selected method unless we have an old-style lookup
   1.111 +  // for a superclass method
   1.112 +  // Invokespecial for a superinterface, resolved method is selected method,
   1.113 +  // no checks for shadowing
   1.114    methodHandle sel_method(THREAD, resolved_method());
   1.115  
   1.116    // check if this is an old-style super call and do a new lookup if so
   1.117    { KlassHandle method_klass  = KlassHandle(THREAD,
   1.118                                              resolved_method->method_holder());
   1.119  
   1.120 -    const bool direct_calling_default_method =
   1.121 -      resolved_klass() != NULL && resolved_method() != NULL &&
   1.122 -      resolved_klass->is_interface() && !resolved_method->is_abstract();
   1.123 -
   1.124 -    if (!direct_calling_default_method &&
   1.125 -        check_access &&
   1.126 +    if (check_access &&
   1.127          // a) check if ACC_SUPER flag is set for the current class
   1.128          (current_klass->is_super() || !AllowNonVirtualCalls) &&
   1.129 -        // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
   1.130 -        current_klass->is_subtype_of(method_klass()) &&
   1.131 -        current_klass() != method_klass() &&
   1.132 +        // b) check if the class of the resolved_klass is a superclass
   1.133 +        // (not supertype in order to exclude interface classes) of the current class.
   1.134 +        // This check is not performed for super.invoke for interface methods
   1.135 +        // in super interfaces.
   1.136 +        current_klass->is_subclass_of(resolved_klass()) &&
   1.137 +        current_klass() != resolved_klass() &&
   1.138          // c) check if the method is not <init>
   1.139          resolved_method->name() != vmSymbols::object_initializer_name()) {
   1.140        // Lookup super method
   1.141 @@ -905,6 +935,23 @@
   1.142                                                        sel_method->signature()));
   1.143    }
   1.144  
   1.145 +  if (TraceItables && Verbose) {
   1.146 +    ResourceMark rm(THREAD);
   1.147 +    tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
   1.148 +                 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
   1.149 +                 Method::name_and_sig_as_C_string(resolved_klass(),
   1.150 +                                                  sel_method->name(),
   1.151 +                                                  sel_method->signature()),
   1.152 +                 sel_method->method_holder()->internal_name()
   1.153 +                );
   1.154 +    sel_method->access_flags().print_on(tty);
   1.155 +    if (sel_method->method_holder()->is_interface() &&
   1.156 +        !sel_method->is_abstract()) {
   1.157 +      tty->print("default");
   1.158 +    }
   1.159 +    tty->cr();
   1.160 +  }
   1.161 +
   1.162    // setup result
   1.163    result.set_static(resolved_klass, sel_method, CHECK);
   1.164  }
   1.165 @@ -927,6 +974,18 @@
   1.166    assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
   1.167    assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
   1.168  
   1.169 +  // check if private interface method
   1.170 +  if (resolved_klass->is_interface() && resolved_method->is_private()) {
   1.171 +    ResourceMark rm(THREAD);
   1.172 +    char buf[200];
   1.173 +    jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s",
   1.174 +                 Method::name_and_sig_as_C_string(resolved_klass(),
   1.175 +                                                  resolved_method->name(),
   1.176 +                                                  resolved_method->signature()),
   1.177 +                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()));
   1.178 +    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   1.179 +  }
   1.180 +
   1.181    // check if not static
   1.182    if (resolved_method->is_static()) {
   1.183      ResourceMark rm(THREAD);
   1.184 @@ -936,6 +995,27 @@
   1.185                                                                                                               resolved_method->signature()));
   1.186      THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   1.187    }
   1.188 +
   1.189 + if (PrintVtables && Verbose) {
   1.190 +   ResourceMark rm(THREAD);
   1.191 +   tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
   1.192 +                  (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
   1.193 +                  (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
   1.194 +                  Method::name_and_sig_as_C_string(resolved_klass(),
   1.195 +                                                   resolved_method->name(),
   1.196 +                                                   resolved_method->signature()),
   1.197 +                  resolved_method->method_holder()->internal_name()
   1.198 +                 );
   1.199 +   resolved_method->access_flags().print_on(tty);
   1.200 +   if (resolved_method->method_holder()->is_interface() &&
   1.201 +       !resolved_method->is_abstract()) {
   1.202 +     tty->print("default");
   1.203 +   }
   1.204 +   if (resolved_method->is_overpass()) {
   1.205 +     tty->print("overpass");
   1.206 +   }
   1.207 +   tty->cr();
   1.208 + }
   1.209  }
   1.210  
   1.211  // throws runtime exceptions
   1.212 @@ -1012,6 +1092,27 @@
   1.213                                                        selected_method->signature()));
   1.214    }
   1.215  
   1.216 +  if (PrintVtables && Verbose) {
   1.217 +    ResourceMark rm(THREAD);
   1.218 +    tty->print("invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ",
   1.219 +                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
   1.220 +                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
   1.221 +                   Method::name_and_sig_as_C_string(resolved_klass(),
   1.222 +                                                    resolved_method->name(),
   1.223 +                                                    resolved_method->signature()),
   1.224 +                   selected_method->method_holder()->internal_name(),
   1.225 +                   vtable_index
   1.226 +                  );
   1.227 +    selected_method->access_flags().print_on(tty);
   1.228 +    if (selected_method->method_holder()->is_interface() &&
   1.229 +        !selected_method->is_abstract()) {
   1.230 +      tty->print("default");
   1.231 +    }
   1.232 +    if (resolved_method->is_overpass()) {
   1.233 +      tty->print("overpass");
   1.234 +    }
   1.235 +    tty->cr();
   1.236 +  }
   1.237    // setup result
   1.238    result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
   1.239  }
   1.240 @@ -1042,6 +1143,17 @@
   1.241      THROW(vmSymbols::java_lang_NullPointerException());
   1.242    }
   1.243  
   1.244 +  // check if private interface method
   1.245 +  if (resolved_klass->is_interface() && resolved_method->is_private()) {
   1.246 +    ResourceMark rm(THREAD);
   1.247 +    char buf[200];
   1.248 +    jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s",
   1.249 +                 Method::name_and_sig_as_C_string(resolved_klass(),
   1.250 +                                                  resolved_method->name(),
   1.251 +                                                  resolved_method->signature()));
   1.252 +    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   1.253 +  }
   1.254 +
   1.255    // check if receiver klass implements the resolved interface
   1.256    if (!recv_klass->is_subtype_of(resolved_klass())) {
   1.257      ResourceMark rm(THREAD);
   1.258 @@ -1071,28 +1183,15 @@
   1.259                                                        resolved_method->signature()));
   1.260    }
   1.261    // check access
   1.262 -  if (sel_method->method_holder()->is_interface()) {
   1.263 -    // Method holder is an interface. Throw Illegal Access Error if sel_method
   1.264 -    // is neither public nor private.
   1.265 -    if (!(sel_method->is_public() || sel_method->is_private())) {
   1.266 -      ResourceMark rm(THREAD);
   1.267 -      THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
   1.268 -                Method::name_and_sig_as_C_string(recv_klass(),
   1.269 -                                                 sel_method->name(),
   1.270 -                                                 sel_method->signature()));
   1.271 -    }
   1.272 +  // Throw Illegal Access Error if sel_method is not public.
   1.273 +  if (!sel_method->is_public()) {
   1.274 +    ResourceMark rm(THREAD);
   1.275 +    THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
   1.276 +              Method::name_and_sig_as_C_string(recv_klass(),
   1.277 +                                               sel_method->name(),
   1.278 +                                               sel_method->signature()));
   1.279    }
   1.280 -  else {
   1.281 -    // Method holder is a class. Throw Illegal Access Error if sel_method
   1.282 -    // is not public.
   1.283 -    if (!sel_method->is_public()) {
   1.284 -      ResourceMark rm(THREAD);
   1.285 -      THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
   1.286 -                Method::name_and_sig_as_C_string(recv_klass(),
   1.287 -                                                 sel_method->name(),
   1.288 -                                                 sel_method->signature()));
   1.289 -    }
   1.290 -  }
   1.291 +
   1.292    // check if abstract
   1.293    if (check_null_and_abstract && sel_method->is_abstract()) {
   1.294      ResourceMark rm(THREAD);
   1.295 @@ -1109,6 +1208,27 @@
   1.296      return;
   1.297    }
   1.298    int itable_index = resolved_method()->itable_index();
   1.299 +
   1.300 +  if (TraceItables && Verbose) {
   1.301 +    ResourceMark rm(THREAD);
   1.302 +    tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
   1.303 +                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
   1.304 +                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
   1.305 +                   Method::name_and_sig_as_C_string(resolved_klass(),
   1.306 +                                                    resolved_method->name(),
   1.307 +                                                    resolved_method->signature()),
   1.308 +                   sel_method->method_holder()->internal_name()
   1.309 +                  );
   1.310 +    sel_method->access_flags().print_on(tty);
   1.311 +    if (sel_method->method_holder()->is_interface() &&
   1.312 +        !sel_method->is_abstract()) {
   1.313 +      tty->print("default");
   1.314 +    }
   1.315 +    if (resolved_method->is_overpass()) {
   1.316 +      tty->print("overpass");
   1.317 +    }
   1.318 +    tty->cr();
   1.319 +  }
   1.320    result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK);
   1.321  }
   1.322  

mercurial