一

{"type":"编程笔记"}


  • Home

  • Archives
  • Search

hotspot source code - mark word

Posted on 2018-08-04   |   In java

vm/oops/markOop.hpp 第30行,关于markOopDesc数据结构的说明,markOop是指向class markOopDesc类型对象的指针,源码如下:

30313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
// The markOop describes the header of an object.//// Note that the mark is not a real oop but just a word.// It is placed in the oop hierarchy for historical reasons.//// Bit-format of an object header (most significant first, big endian layout below):////  32 bits://  --------//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)//             size:32 ------------------------------------------>| (CMS free block)//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)////  64 bits://  --------//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)//  size:64 ----------------------------------------------------->| (CMS free block)////  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)////  - hash contains the identity hash value: largest value is//    31 bits, see os::random().  Also, 64-bit vm's require//    a hash value no bigger than 32 bits because they will not//    properly generate a mask larger than that: see library_call.cpp//    and c1_CodePatterns_sparc.cpp.////  - the biased lock pattern is used to bias a lock toward a given//    thread. When this pattern is set in the low three bits, the lock//    is either biased toward a given thread or "anonymously" biased,//    indicating that it is possible for it to be biased. When the//    lock is biased toward a given thread, locking and unlocking can//    be performed by that thread without using atomic operations.//    When a lock's bias is revoked, it reverts back to the normal//    locking scheme described below.////    Note that we are overloading the meaning of the "unlocked" state//    of the header. Because we steal a bit from the age we can//    guarantee that the bias pattern will never be seen for a truly//    unlocked object.////    Note also that the biased state contains the age bits normally//    contained in the object header. Large increases in scavenge//    times were seen when these bits were absent and an arbitrary age//    assigned to all biased objects, because they tended to consume a//    significant fraction of the eden semispaces and were not//    promoted promptly, causing an increase in the amount of copying//    performed. The runtime system aligns all JavaThread* pointers to//    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))//    to make room for the age bits & the epoch bits (used in support of//    biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).////    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread//    [0           | epoch | age | 1 | 01]       lock is anonymously biased////  - the two lock bits are used to describe three states: locked/unlocked and monitor.////    [ptr             | 00]  locked             ptr points to real header on stack//    [header      | 0 | 01]  unlocked           regular object header//    [ptr             | 10]  monitor            inflated lock (header is wapped out)//    [ptr             | 11]  marked             used by markSweep to mark an object//                                               not valid at any other time////    We assume that stack/thread pointers have the lowest two bits cleared.class BasicLock;class ObjectMonitor;class JavaThread;class markOopDesc: public oopDesc { private:  // Conversion  uintptr_t value() const { return (uintptr_t) this; } public:  // Constants  enum { age_bits                 = 4,         lock_bits                = 2,         biased_lock_bits         = 1,         max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,         hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,         cms_bits                 = LP64_ONLY(1) NOT_LP64(0),         epoch_bits               = 2  };  // The biased locking code currently requires that the age bits be  // contiguous to the lock bits.  enum { lock_shift               = 0,         biased_lock_shift        = lock_bits,         age_shift                = lock_bits + biased_lock_bits,         cms_shift                = age_shift + age_bits,         hash_shift               = cms_shift + cms_bits,         epoch_shift              = hash_shift  };  enum { lock_mask                = right_n_bits(lock_bits),         lock_mask_in_place       = lock_mask << lock_shift,         biased_lock_mask         = right_n_bits(lock_bits + biased_lock_bits),         biased_lock_mask_in_place= biased_lock_mask << lock_shift,         biased_lock_bit_in_place = 1 << biased_lock_shift,         age_mask                 = right_n_bits(age_bits),         age_mask_in_place        = age_mask << age_shift,         epoch_mask               = right_n_bits(epoch_bits),         epoch_mask_in_place      = epoch_mask << epoch_shift,         cms_mask                 = right_n_bits(cms_bits),         cms_mask_in_place        = cms_mask << cms_shift#ifndef _WIN64         ,hash_mask               = right_n_bits(hash_bits),         hash_mask_in_place       = (address_word)hash_mask << hash_shift#endif  };  // Alignment of JavaThread pointers encoded in object header required by biased locking  enum { biased_lock_alignment    = 2 << (epoch_shift + epoch_bits)  };#ifdef _WIN64    // These values are too big for Win64    const static uintptr_t hash_mask = right_n_bits(hash_bits);    const static uintptr_t hash_mask_in_place  =                            (address_word)hash_mask << hash_shift;#endif  enum { locked_value             = 0,         unlocked_value           = 1,         monitor_value            = 2,         marked_value             = 3,         biased_lock_pattern      = 5  };  enum { no_hash                  = 0 };  // no hash value assigned  enum { no_hash_in_place         = (address_word)no_hash << hash_shift,         no_lock_in_place         = unlocked_value  };  enum { max_age                  = age_mask };  enum { max_bias_epoch           = epoch_mask };  // Biased Locking accessors.  // These must be checked by all code which calls into the  // ObjectSynchronizer and other code. The biasing is not understood  // by the lower-level CAS-based locking code, although the runtime  // fixes up biased locks to be compatible with it when a bias is  // revoked.  bool has_bias_pattern() const {    return (mask_bits(value(), biased_lock_mask_in_place) == biased_lock_pattern);  }  JavaThread* biased_locker() const {    assert(has_bias_pattern(), "should not call this otherwise");    return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place))));  }  // Indicates that the mark has the bias bit set but that it has not  // yet been biased toward a particular thread  bool is_biased_anonymously() const {    return (has_bias_pattern() && (biased_locker() == NULL));  }  // Indicates epoch in which this bias was acquired. If the epoch  // changes due to too many bias revocations occurring, the biases  // from the previous epochs are all considered invalid.  int bias_epoch() const {    assert(has_bias_pattern(), "should not call this otherwise");    return (mask_bits(value(), epoch_mask_in_place) >> epoch_shift);  }  markOop set_bias_epoch(int epoch) {    assert(has_bias_pattern(), "should not call this otherwise");    assert((epoch & (~epoch_mask)) == 0, "epoch overflow");    return markOop(mask_bits(value(), ~epoch_mask_in_place) | (epoch << epoch_shift));  }  markOop incr_bias_epoch() {    return set_bias_epoch((1 + bias_epoch()) & epoch_mask);  }  // Prototype mark for initialization  static markOop biased_locking_prototype() {    return markOop( biased_lock_pattern );  }  // lock accessors (note that these assume lock_shift == 0)  bool is_locked()   const {    return (mask_bits(value(), lock_mask_in_place) != unlocked_value);  }  bool is_unlocked() const {    return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value);  }  bool is_marked()   const {    return (mask_bits(value(), lock_mask_in_place) == marked_value);  }  bool is_neutral()  const { return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value); }  // Special temporary state of the markOop while being inflated.  // Code that looks at mark outside a lock need to take this into account.  bool is_being_inflated() const { return (value() == 0); }  // Distinguished markword value - used when inflating over  // an existing stacklock.  0 indicates the markword is "BUSY".  // Lockword mutators that use a LD...CAS idiom should always  // check for and avoid overwriting a 0 value installed by some  // other thread.  (They should spin or block instead.  The 0 value  // is transient and *should* be short-lived).  static markOop INFLATING() { return (markOop) 0; }    // inflate-in-progress  // Should this header be preserved during GC?  inline bool must_be_preserved(oop obj_containing_mark) const;  inline bool must_be_preserved_with_bias(oop obj_containing_mark) const;  // Should this header (including its age bits) be preserved in the  // case of a promotion failure during scavenge?  // Note that we special case this situation. We want to avoid  // calling BiasedLocking::preserve_marks()/restore_marks() (which  // decrease the number of mark words that need to be preserved  // during GC) during each scavenge. During scavenges in which there  // is no promotion failure, we actually don't need to call the above  // routines at all, since we don't mutate and re-initialize the  // marks of promoted objects using init_mark(). However, during  // scavenges which result in promotion failure, we do re-initialize  // the mark words of objects, meaning that we should have called  // these mark word preservation routines. Currently there's no good  // place in which to call them in any of the scavengers (although  // guarded by appropriate locks we could make one), but the  // observation is that promotion failures are quite rare and  // reducing the number of mark words preserved during them isn't a  // high priority.  inline bool must_be_preserved_for_promotion_failure(oop obj_containing_mark) const;  inline bool must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const;  // Should this header be preserved during a scavenge where CMS is  // the old generation?  // (This is basically the same body as must_be_preserved_for_promotion_failure(),  // but takes the Klass* as argument instead)  inline bool must_be_preserved_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;  inline bool must_be_preserved_with_bias_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;  // WARNING: The following routines are used EXCLUSIVELY by  // synchronization functions. They are not really gc safe.  // They must get updated if markOop layout get changed.  markOop set_unlocked() const {    return markOop(value() | unlocked_value);  }  bool has_locker() const {    return ((value() & lock_mask_in_place) == locked_value);  }  BasicLock* locker() const {    assert(has_locker(), "check");    return (BasicLock*) value();  }  bool has_monitor() const {    return ((value() & monitor_value) != 0);  }  ObjectMonitor* monitor() const {    assert(has_monitor(), "check");    // Use xor instead of &~ to provide one extra tag-bit check.    return (ObjectMonitor*) (value() ^ monitor_value);  }  bool has_displaced_mark_helper() const {    return ((value() & unlocked_value) == 0);  }  markOop displaced_mark_helper() const {    assert(has_displaced_mark_helper(), "check");    intptr_t ptr = (value() & ~monitor_value);    return *(markOop*)ptr;  }  void set_displaced_mark_helper(markOop m) const {    assert(has_displaced_mark_helper(), "check");    intptr_t ptr = (value() & ~monitor_value);    *(markOop*)ptr = m;  }
Read more »

hotspot source code - klass and oop

Posted on 2018-08-04   |   In java

OOP-Klass 二分模型

  1. OOP是指ordinary object pointer,普通对象指针,用来描述 JVM 中的实例对象的实例信息。
  2. Klass是 Java 类在 C++ 中的对等体,用来描述 Java 类,在其中包括了类的相关信息。

这个模型也体现了编程设计的最根本的一个设计原则:分离变化的与不变化的部分。其中 Java 实例信息相对 Java 类而言,是包含了变化的部分数据,Java 类描述了类的行为和类信息,为所有实例所共享。这个二分模型中的 Klass 向 JVM 提供了二个功能:

  1. 实现语言层面的 Java 类
  2. 实现 Java 对象的方法分发(dispatch)功能

oop 基类

vm/oops/oop.hpp 第35行,**OopDesc类型都继承自class oopDesc,源码如下:

30313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
// oopDesc is the top baseclass for objects classes.  The {name}Desc classes describe// the format of Java objects so the fields can be accessed from C++.// oopDesc is abstract.// (see oopHierarchy for complete oop class hierarchy)//// no virtual functions allowed// store into oop with store checktemplate <class T> void oop_store(T* p, oop v);template <class T> void oop_store(volatile T* p, oop v);extern bool always_do_update_barrier;// Forward declarations.class OopClosure;class ScanClosure;class FastScanClosure;class FilteringClosure;class BarrierSet;class CMSIsAliveClosure;class PSPromotionManager;class ParCompactionManager;class oopDesc {  friend class VMStructs; private:  volatile markOop  _mark;  union _metadata {    Klass*      _klass;    narrowKlass _compressed_klass;  } _metadata;  // Fast access to barrier set.  Must be initialized.  static BarrierSet* _bs; public:  markOop  mark() const         { return _mark; }  markOop* mark_addr() const    { return (markOop*) &_mark; }  void set_mark(volatile markOop m)      { _mark = m;   }  void    release_set_mark(markOop m);  markOop cas_set_mark(markOop new_mark, markOop old_mark);  // Used only to re-initialize the mark word (e.g., of promoted  // objects during a GC) -- requires a valid klass pointer  void init_mark();  Klass* klass() const;  Klass* klass_or_null() const volatile;  Klass** klass_addr();  narrowKlass* compressed_klass_addr();  void set_klass(Klass* k);  // For klass field compression  int klass_gap() const;  void set_klass_gap(int z);  // For when the klass pointer is being used as a linked list "next" field.  void set_klass_to_list_ptr(oop k);  oop list_ptr_from_klass();  // size of object header, aligned to platform wordSize  static int header_size()          { return sizeof(oopDesc)/HeapWordSize; }  // Returns whether this is an instance of k or an instance of a subclass of k  bool is_a(Klass* k)  const;  // Returns the actual oop size of the object  int size();  // Sometimes (for complicated concurrency-related reasons), it is useful  // to be able to figure out the size of an object knowing its klass.  int size_given_klass(Klass* klass);  // type test operations (inlined in oop.inline.h)  bool is_instance()            const;  bool is_instanceMirror()      const;  bool is_instanceClassLoader() const;  bool is_instanceRef()         const;  bool is_array()               const;  bool is_objArray()            const;  bool is_typeArray()           const;
Read more »

hotspot source code - class file parse

Posted on 2018-08-04   |   In java

Java 的版本号定义如下:

80818283848586878889909192939495
// Used for two backward compatibility reasons:// - to check for new additions to the class file format in JDK1.5// - to check for bug fixes in the format checker in JDK1.5#define JAVA_1_5_VERSION                  49// Used for backward compatibility reasons:// - to check for javac bug fixes that happened after 1.5// - also used as the max version when running in jdk6#define JAVA_6_VERSION                    50// Used for backward compatibility reasons:// - to check NameAndType_info signatures more aggressively#define JAVA_7_VERSION                    51// Extension method support.#define JAVA_8_VERSION                    52

Java7 常量池中新增加了3个常量类型,如InvokeDynamic,MethodHandle和MethodType,Java7 发布时 JVM 中新增加了一个指令invokedynamic,在常量池解析时就会碰到与这个指令直接相关的新增加的3个常量类型和新增加的属性BootstrapMethods:

979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
void ClassFileParser::parse_constant_pool_entries(int length, TRAPS) {  // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize  // this function (_current can be allocated in a register, with scalar  // replacement of aggregates). The _current pointer is copied back to  // stream() when this function returns. DON'T call another method within  // this method that uses stream().  ClassFileStream* cfs0 = stream();  ClassFileStream cfs1 = *cfs0;  ClassFileStream* cfs = &cfs1;#ifdef ASSERT  assert(cfs->allocated_on_stack(),"should be local");  u1* old_current = cfs0->current();#endif  Handle class_loader(THREAD, _loader_data->class_loader());  // Used for batching symbol allocations.  const char* names[SymbolTable::symbol_alloc_batch_size];  int lengths[SymbolTable::symbol_alloc_batch_size];  int indices[SymbolTable::symbol_alloc_batch_size];  unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];  int names_count = 0;  // parsing  Index 0 is unused  for (int index = 1; index < length; index++) {    // Each of the following case guarantees one more byte in the stream    // for the following tag or the access_flags following constant pool,    // so we don't need bounds-check for reading tag.    u1 tag = cfs->get_u1_fast();    switch (tag) {      case JVM_CONSTANT_Class :        {          cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags          u2 name_index = cfs->get_u2_fast();          _cp->klass_index_at_put(index, name_index);        }        break;      case JVM_CONSTANT_Fieldref :        {          cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags          u2 class_index = cfs->get_u2_fast();          u2 name_and_type_index = cfs->get_u2_fast();          _cp->field_at_put(index, class_index, name_and_type_index);        }        break;      case JVM_CONSTANT_Methodref :        {          cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags          u2 class_index = cfs->get_u2_fast();          u2 name_and_type_index = cfs->get_u2_fast();          _cp->method_at_put(index, class_index, name_and_type_index);        }        break;      case JVM_CONSTANT_InterfaceMethodref :        {          cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags          u2 class_index = cfs->get_u2_fast();          u2 name_and_type_index = cfs->get_u2_fast();          _cp->interface_method_at_put(index, class_index, name_and_type_index);        }        break;      case JVM_CONSTANT_String :        {          cfs->guarantee_more(3, CHECK);  // string_index, tag/access_flags          u2 string_index = cfs->get_u2_fast();          _cp->string_index_at_put(index, string_index);        }        break;      case JVM_CONSTANT_MethodHandle :      case JVM_CONSTANT_MethodType :        if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {          classfile_parse_error(            "Class file version does not support constant tag %u in class file %s",            tag, CHECK);        }        if (!EnableInvokeDynamic) {          classfile_parse_error(            "This JVM does not support constant tag %u in class file %s",            tag, CHECK);        }        if (tag == JVM_CONSTANT_MethodHandle) {          cfs->guarantee_more(4, CHECK);  // ref_kind, method_index, tag/access_flags          u1 ref_kind = cfs->get_u1_fast();          u2 method_index = cfs->get_u2_fast();          _cp->method_handle_index_at_put(index, ref_kind, method_index);        } else if (tag == JVM_CONSTANT_MethodType) {          cfs->guarantee_more(3, CHECK);  // signature_index, tag/access_flags          u2 signature_index = cfs->get_u2_fast();          _cp->method_type_index_at_put(index, signature_index);        } else {          ShouldNotReachHere();        }        break;      case JVM_CONSTANT_InvokeDynamic :        {          if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {            classfile_parse_error(              "Class file version does not support constant tag %u in class file %s",              tag, CHECK);          }          if (!EnableInvokeDynamic) {            classfile_parse_error(              "This JVM does not support constant tag %u in class file %s",              tag, CHECK);          }          cfs->guarantee_more(5, CHECK);  // bsm_index, nt, tag/access_flags          u2 bootstrap_specifier_index = cfs->get_u2_fast();          u2 name_and_type_index = cfs->get_u2_fast();          if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)            _max_bootstrap_specifier_index = (int) bootstrap_specifier_index;  // collect for later          _cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);        }        break;      case JVM_CONSTANT_Integer :        {          cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags          u4 bytes = cfs->get_u4_fast();          _cp->int_at_put(index, (jint) bytes);        }        break;      case JVM_CONSTANT_Float :        {          cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags          u4 bytes = cfs->get_u4_fast();          _cp->float_at_put(index, *(jfloat*)&bytes);        }        break;      case JVM_CONSTANT_Long :        // A mangled type might cause you to overrun allocated memory        guarantee_property(index+1 < length,                           "Invalid constant pool entry %u in class file %s",                           index, CHECK);        {          cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags          u8 bytes = cfs->get_u8_fast();          _cp->long_at_put(index, bytes);        }        index++;   // Skip entry following eigth-byte constant, see JVM book p. 98        break;      case JVM_CONSTANT_Double :        // A mangled type might cause you to overrun allocated memory        guarantee_property(index+1 < length,                           "Invalid constant pool entry %u in class file %s",                           index, CHECK);        {          cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags          u8 bytes = cfs->get_u8_fast();          _cp->double_at_put(index, *(jdouble*)&bytes);        }        index++;   // Skip entry following eigth-byte constant, see JVM book p. 98        break;      case JVM_CONSTANT_NameAndType :        {          cfs->guarantee_more(5, CHECK);  // name_index, signature_index, tag/access_flags          u2 name_index = cfs->get_u2_fast();          u2 signature_index = cfs->get_u2_fast();          _cp->name_and_type_at_put(index, name_index, signature_index);        }        break;      case JVM_CONSTANT_Utf8 :        {          cfs->guarantee_more(2, CHECK);  // utf8_length          u2  utf8_length = cfs->get_u2_fast();          u1* utf8_buffer = cfs->get_u1_buffer();          assert(utf8_buffer != NULL, "null utf8 buffer");          // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.          cfs->guarantee_more(utf8_length+1, CHECK);  // utf8 string, tag/access_flags          cfs->skip_u1_fast(utf8_length);          // Before storing the symbol, make sure it's legal          if (_need_verify) {            verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);          }          if (EnableInvokeDynamic && has_cp_patch_at(index)) {            Handle patch = clear_cp_patch_at(index);            guarantee_property(java_lang_String::is_instance(patch()),                               "Illegal utf8 patch at %d in class file %s",                               index, CHECK);            char* str = java_lang_String::as_utf8_string(patch());            // (could use java_lang_String::as_symbol instead, but might as well batch them)            utf8_buffer = (u1*) str;            utf8_length = (u2) strlen(str);          }          unsigned int hash;          Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);          if (result == NULL) {            names[names_count] = (char*)utf8_buffer;            lengths[names_count] = utf8_length;            indices[names_count] = index;            hashValues[names_count++] = hash;            if (names_count == SymbolTable::symbol_alloc_batch_size) {              SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);              names_count = 0;            }          } else {            _cp->symbol_at_put(index, result);          }        }        break;      default:        classfile_parse_error(          "Unknown constant tag %u in class file %s", tag, CHECK);        break;    }  }  // Allocate the remaining symbols  if (names_count > 0) {    SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK);  }  // Copy _current pointer of local copy back to stream().#ifdef ASSERT  assert(cfs0->current() == old_current, "non-exclusive use of stream()");#endif  cfs0->set_current(cfs1.current());}

第2807行关于BootstrapMethods属性相关的解析:

280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_byte_length, TRAPS) {  ClassFileStream* cfs = stream();  u1* current_start = cfs->current();  guarantee_property(attribute_byte_length >= sizeof(u2),                     "Invalid BootstrapMethods attribute length %u in class file %s",                     attribute_byte_length,                     CHECK);  cfs->guarantee_more(attribute_byte_length, CHECK);  int attribute_array_length = cfs->get_u2_fast();  guarantee_property(_max_bootstrap_specifier_index < attribute_array_length,                     "Short length on BootstrapMethods in class file %s",                     CHECK);  // The attribute contains a counted array of counted tuples of shorts,  // represending bootstrap specifiers:  //    length*{bootstrap_method_index, argument_count*{argument_index}}  int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2);  // operand_count = number of shorts in attr, except for leading length  // The attribute is copied into a short[] array.  // The array begins with a series of short[2] pairs, one for each tuple.  int index_size = (attribute_array_length * 2);  Array<u2>* operands = MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);  // Eagerly assign operands so they will be deallocated with the constant  // pool if there is an error.  _cp->set_operands(operands);  int operand_fill_index = index_size;  int cp_size = _cp->length();  for (int n = 0; n < attribute_array_length; n++) {    // Store a 32-bit offset into the header of the operand array.    ConstantPool::operand_offset_at_put(operands, n, operand_fill_index);    // Read a bootstrap specifier.    cfs->guarantee_more(sizeof(u2) * 2, CHECK);  // bsm, argc    u2 bootstrap_method_index = cfs->get_u2_fast();    u2 argument_count = cfs->get_u2_fast();    check_property(      valid_cp_range(bootstrap_method_index, cp_size) &&      _cp->tag_at(bootstrap_method_index).is_method_handle(),      "bootstrap_method_index %u has bad constant type in class file %s",      bootstrap_method_index,      CHECK);    guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(),      "Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s",      CHECK);    operands->at_put(operand_fill_index++, bootstrap_method_index);    operands->at_put(operand_fill_index++, argument_count);    cfs->guarantee_more(sizeof(u2) * argument_count, CHECK);  // argv[argc]    for (int j = 0; j < argument_count; j++) {      u2 argument_index = cfs->get_u2_fast();      check_property(        valid_cp_range(argument_index, cp_size) &&        _cp->tag_at(argument_index).is_loadable_constant(),        "argument_index %u has bad constant type in class file %s",        argument_index,        CHECK);      operands->at_put(operand_fill_index++, argument_index);    }  }  assert(operand_fill_index == operands->length(), "exact fill");  u1* current_end = cfs->current();  guarantee_property(current_end == current_start + attribute_byte_length,                     "Bad length on BootstrapMethods in class file %s",                     CHECK);}
Read more »

hotspot source code - call java main method

Posted on 2018-08-04   |   In java

vm/prims/jni.cpp 第1311行,jni_invoke_static()方法中第1329行通过JavaCalls::call()方法调用 Java 的main(String[])方法,源码如下:

13111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {  methodHandle method(THREAD, Method::resolve_jmethod_id(method_id));  // Create object to hold arguments for the JavaCall, and associate it with  // the jni parser  ResourceMark rm(THREAD);  int number_of_parameters = method->size_of_parameters();  JavaCallArguments java_args(number_of_parameters);  args->set_java_argument_object(&java_args);  assert(method->is_static(), "method should be static");  // Fill out JavaCallArguments object  args->iterate( Fingerprinter(method).fingerprint() );  // Initialize result type  result->set_type(args->get_ret_type());  // Invoke the method. Result is returned as oop.  JavaCalls::call(result, method, &java_args, CHECK);  // Convert result  if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {    result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));  }}
Read more »

hotspot source code - jvm create

Posted on 2018-08-04   |   In java

JVM 虚拟机创建

进入vm/runtime/thread.cpp文件的第3317行,查看主要方法Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain),源码如下:

Read more »
1…567…99
yuweijun

yuweijun

492 posts
12 categories
RSS
GitHub Twitter
© 2021 yuweijun
Powered by Hexo
Theme - NexT.Mist.KISS