0N/A/*
3147N/A * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
1879N/A#include "precompiled.hpp"
1879N/A#include "classfile/javaClasses.hpp"
1879N/A#include "classfile/symbolTable.hpp"
1879N/A#include "classfile/systemDictionary.hpp"
1879N/A#include "classfile/vmSymbols.hpp"
1879N/A#include "interpreter/linkResolver.hpp"
1879N/A#include "memory/oopFactory.hpp"
1879N/A#include "memory/universe.inline.hpp"
1879N/A#include "oops/constantPoolOop.hpp"
1879N/A#include "oops/instanceKlass.hpp"
1879N/A#include "oops/objArrayKlass.hpp"
1879N/A#include "oops/oop.inline.hpp"
1879N/A#include "runtime/fieldType.hpp"
1879N/A#include "runtime/init.hpp"
1879N/A#include "runtime/signature.hpp"
1879N/A#include "runtime/vframe.hpp"
0N/A
431N/Avoid constantPoolOopDesc::set_flag_at(FlagBit fb) {
431N/A const int MAX_STATE_CHANGES = 2;
431N/A for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
431N/A int oflags = _flags;
431N/A int nflags = oflags | (1 << (int)fb);
431N/A if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags)
431N/A return;
431N/A }
431N/A assert(false, "failed to cmpxchg flags");
431N/A _flags |= (1 << (int)fb); // better than nothing
431N/A}
431N/A
0N/AklassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
2062N/A // A resolved constantPool entry will contain a klassOop, otherwise a Symbol*.
0N/A // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
0N/A // tag is not updated atomicly.
2062N/A CPSlot entry = this_oop->slot_at(which);
2062N/A if (entry.is_oop()) {
2062N/A assert(entry.get_oop()->is_klass(), "must be");
0N/A // Already resolved - return entry.
2062N/A return (klassOop)entry.get_oop();
0N/A }
0N/A
0N/A // Acquire lock on constant oop while doing update. After we get the lock, we check if another object
0N/A // already has updated the object
0N/A assert(THREAD->is_Java_thread(), "must be a Java thread");
0N/A bool do_resolve = false;
0N/A bool in_error = false;
0N/A
2062N/A Symbol* name = NULL;
0N/A Handle loader;
0N/A { ObjectLocker ol(this_oop, THREAD);
0N/A
0N/A if (this_oop->tag_at(which).is_unresolved_klass()) {
0N/A if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
0N/A in_error = true;
0N/A } else {
0N/A do_resolve = true;
2062N/A name = this_oop->unresolved_klass_at(which);
0N/A loader = Handle(THREAD, instanceKlass::cast(this_oop->pool_holder())->class_loader());
0N/A }
0N/A }
0N/A } // unlocking constantPool
0N/A
0N/A
0N/A // The original attempt to resolve this constant pool entry failed so find the
0N/A // original error and throw it again (JVMS 5.4.3).
0N/A if (in_error) {
2062N/A Symbol* error = SystemDictionary::find_resolution_error(this_oop, which);
2062N/A guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
0N/A ResourceMark rm;
0N/A // exception text will be the class name
0N/A const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
0N/A THROW_MSG_0(error, className);
0N/A }
0N/A
0N/A if (do_resolve) {
0N/A // this_oop must be unlocked during resolve_or_fail
0N/A oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
0N/A Handle h_prot (THREAD, protection_domain);
0N/A klassOop k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
0N/A KlassHandle k;
0N/A if (!HAS_PENDING_EXCEPTION) {
0N/A k = KlassHandle(THREAD, k_oop);
0N/A // Do access check for klasses
0N/A verify_constant_pool_resolve(this_oop, k, THREAD);
0N/A }
0N/A
0N/A // Failed to resolve class. We must record the errors so that subsequent attempts
0N/A // to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
0N/A if (HAS_PENDING_EXCEPTION) {
0N/A ResourceMark rm;
2062N/A Symbol* error = PENDING_EXCEPTION->klass()->klass_part()->name();
0N/A
0N/A bool throw_orig_error = false;
0N/A {
0N/A ObjectLocker ol (this_oop, THREAD);
0N/A
0N/A // some other thread has beaten us and has resolved the class.
0N/A if (this_oop->tag_at(which).is_klass()) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A entry = this_oop->resolved_klass_at(which);
2062N/A return (klassOop)entry.get_oop();
0N/A }
0N/A
0N/A if (!PENDING_EXCEPTION->
1142N/A is_a(SystemDictionary::LinkageError_klass())) {
0N/A // Just throw the exception and don't prevent these classes from
0N/A // being loaded due to virtual machine errors like StackOverflow
0N/A // and OutOfMemoryError, etc, or if the thread was hit by stop()
0N/A // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
0N/A }
0N/A else if (!this_oop->tag_at(which).is_unresolved_klass_in_error()) {
0N/A SystemDictionary::add_resolution_error(this_oop, which, error);
0N/A this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
0N/A } else {
0N/A // some other thread has put the class in error state.
2062N/A error = SystemDictionary::find_resolution_error(this_oop, which);
2062N/A assert(error != NULL, "checking");
0N/A throw_orig_error = true;
0N/A }
0N/A } // unlocked
0N/A
0N/A if (throw_orig_error) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A ResourceMark rm;
0N/A const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
0N/A THROW_MSG_0(error, className);
0N/A }
0N/A
0N/A return 0;
0N/A }
0N/A
0N/A if (TraceClassResolution && !k()->klass_part()->oop_is_array()) {
0N/A // skip resolving the constant pool so that this code get's
0N/A // called the next time some bytecodes refer to this class.
0N/A ResourceMark rm;
0N/A int line_number = -1;
0N/A const char * source_file = NULL;
0N/A if (JavaThread::current()->has_last_Java_frame()) {
0N/A // try to identify the method which called this function.
0N/A vframeStream vfst(JavaThread::current());
0N/A if (!vfst.at_end()) {
0N/A line_number = vfst.method()->line_number_from_bci(vfst.bci());
2062N/A Symbol* s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
0N/A if (s != NULL) {
0N/A source_file = s->as_C_string();
0N/A }
0N/A }
0N/A }
0N/A if (k() != this_oop->pool_holder()) {
0N/A // only print something if the classes are different
0N/A if (source_file != NULL) {
0N/A tty->print("RESOLVE %s %s %s:%d\n",
0N/A instanceKlass::cast(this_oop->pool_holder())->external_name(),
0N/A instanceKlass::cast(k())->external_name(), source_file, line_number);
0N/A } else {
0N/A tty->print("RESOLVE %s %s\n",
0N/A instanceKlass::cast(this_oop->pool_holder())->external_name(),
0N/A instanceKlass::cast(k())->external_name());
0N/A }
0N/A }
0N/A return k();
0N/A } else {
0N/A ObjectLocker ol (this_oop, THREAD);
0N/A // Only updated constant pool - if it is resolved.
0N/A do_resolve = this_oop->tag_at(which).is_unresolved_klass();
0N/A if (do_resolve) {
0N/A this_oop->klass_at_put(which, k());
0N/A }
0N/A }
0N/A }
0N/A
0N/A entry = this_oop->resolved_klass_at(which);
2062N/A assert(entry.is_oop() && entry.get_oop()->is_klass(), "must be resolved at this point");
2062N/A return (klassOop)entry.get_oop();
0N/A}
0N/A
0N/A
0N/A// Does not update constantPoolOop - to avoid any exception throwing. Used
0N/A// by compiler and exception handling. Also used to avoid classloads for
0N/A// instanceof operations. Returns NULL if the class has not been loaded or
0N/A// if the verification of constant pool failed
0N/AklassOop constantPoolOopDesc::klass_at_if_loaded(constantPoolHandle this_oop, int which) {
2062N/A CPSlot entry = this_oop->slot_at(which);
2062N/A if (entry.is_oop()) {
2062N/A assert(entry.get_oop()->is_klass(), "must be");
2062N/A return (klassOop)entry.get_oop();
0N/A } else {
2062N/A assert(entry.is_metadata(), "must be either symbol or klass");
0N/A Thread *thread = Thread::current();
2062N/A Symbol* name = entry.get_symbol();
0N/A oop loader = instanceKlass::cast(this_oop->pool_holder())->class_loader();
0N/A oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
0N/A Handle h_prot (thread, protection_domain);
0N/A Handle h_loader (thread, loader);
0N/A klassOop k = SystemDictionary::find(name, h_loader, h_prot, thread);
0N/A
0N/A if (k != NULL) {
0N/A // Make sure that resolving is legal
0N/A EXCEPTION_MARK;
0N/A KlassHandle klass(THREAD, k);
0N/A // return NULL if verification fails
0N/A verify_constant_pool_resolve(this_oop, klass, THREAD);
0N/A if (HAS_PENDING_EXCEPTION) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A return NULL;
0N/A }
0N/A return klass();
0N/A } else {
0N/A return k;
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/AklassOop constantPoolOopDesc::klass_ref_at_if_loaded(constantPoolHandle this_oop, int which) {
0N/A return klass_at_if_loaded(this_oop, this_oop->klass_ref_index_at(which));
0N/A}
0N/A
0N/A
0N/A// This is an interface for the compiler that allows accessing non-resolved entries
0N/A// in the constant pool - but still performs the validations tests. Must be used
0N/A// in a pre-parse of the compiler - to determine what it can do and not do.
0N/A// Note: We cannot update the ConstantPool from the vm_thread.
0N/AklassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int index, TRAPS) {
0N/A int which = this_oop->klass_ref_index_at(index);
2062N/A CPSlot entry = this_oop->slot_at(which);
2062N/A if (entry.is_oop()) {
2062N/A assert(entry.get_oop()->is_klass(), "must be");
2062N/A return (klassOop)entry.get_oop();
0N/A } else {
2062N/A assert(entry.is_metadata(), "must be either symbol or klass");
2062 Error!

 

There was an error!

null

java.lang.NullPointerException