Top


定義場所(file name)

hotspot/src/share/vm/prims/jni.cpp

名前(function name)

JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))

本体部(body)

  {- -------------------------------------------
  (1) (デバッグ用の処理)
      (See: JNIWrapper)
      ---------------------------------------- -}

      JNIWrapper("GetObjectField");

  {- -------------------------------------------
  (1) (DTrace のフック点)
      ---------------------------------------- -}

      DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID);

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      oop o = JNIHandles::resolve_non_null(obj);
      klassOop k = o->klass();
      int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);

  {- -------------------------------------------
  (1) (JVMTI のフック点)
      ---------------------------------------- -}

      // Keep JVMTI addition small and only check enabled flag here.
      // jni_GetField_probe() assumes that is okay to create handles.
      if (JvmtiExport::should_post_field_access()) {
        o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
      }

  {- -------------------------------------------
  (1) oopDesc::obj_field() でフィールドの値を取得し, その結果を JNI Handle 化しておく.
      ---------------------------------------- -}

      jobject ret = JNIHandles::make_local(env, o->obj_field(offset));

  {- -------------------------------------------
  (1) 以下は G1GC の場合のみの処理.
      G1SATBCardTableModRefBS::enqueue() を呼んで取得した値を記録しておく
      (G1 の場合は SATB 方式での concurrent marking 処理があるため, 
      java.lang.ref.Reference オブジェクトの referent フィールドを取得する時には, 
      referent  フィールドの値を記録しておかなければいけない)

      (他のオブジェクトのフィールドは read するだけなら値は変わらないので write 時にのみ SATB バリアを掛けている.
      一方, java.lang.ref.Reference のフィールドは write されなくても消えることがある.

      write だけでなく read もされてなければ不整合は起こらないが, write されずに read だけされ, しかも値が消えると不整合が起こりうる(と思われる).
      そのため, こいつだけは read 時にも SATB バリアを掛けている(模様))
      ---------------------------------------- -}

    #ifndef SERIALGC
      // If G1 is enabled and we are accessing the value of the referent
      // field in a reference object then we need to register a non-null
      // referent with the SATB barrier.
      if (UseG1GC) {
        bool needs_barrier = false;

        if (ret != NULL &&
            offset == java_lang_ref_Reference::referent_offset &&
            instanceKlass::cast(k)->reference_type() != REF_NONE) {
          assert(instanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity");
          needs_barrier = true;
        }

        if (needs_barrier) {
          oop referent = JNIHandles::resolve(ret);
          G1SATBCardTableModRefBS::enqueue(referent);
        }
      }
    #endif // SERIALGC

  {- -------------------------------------------
  (1) (DTrace のフック点)
      ---------------------------------------- -}

      DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret);

  {- -------------------------------------------
  (1) 結果をリターン
      ---------------------------------------- -}

      return ret;
    JNI_END

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.