Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6751861

Memory leak occurs in JVMTI(jdk5.0u16)

XMLWordPrintable

    • b03
    • x86
    • linux_redhat_3.0, windows_xp

        When a customer used JVMTI in jdk5, memory leaks.
        Specifically speaking, when a callback function is set for the event
        of JVMTI_EVENT_THREAD_START, this leak occurs.

        The following source code portions are based on jdk5.0u16.

        When a call back function is set for the event of JVMTI_EVENT_THREAD_START,
        every time Java application creates threads, JvmtiThreadState is created in JVM.
        At the line# 49( constructor of JvmtiThreadState and GrowableArray),
        the second argument is set to true.

        ----
          [hotspot/src/share/vm/prims/jvmtiThreadState.cpp]
           30 JvmtiThreadState::JvmtiThreadState(JavaThread* thread)
            ...
           47 // add all the JvmtiEnvThreadState to the new JvmtiThreadState
           48 int ec = JvmtiEnvBase::env_count();
           49 _env_thread_states = new (ResourceObj::C_HEAP) GrowableArray<JvmtiEnvThreadState *>(ec+1,true);
            ...
           66 }
        -----

        When the second argument is true, the field "_data" in GrowableArray is allocated to c heap.
        Because there is no destructor for GrowableArray, to call clear_and_deallocate() and
        release _data are needed before the release of GrowableArray.

          [hotspot/src/share/vm/utilities/growableArray.cpp]
           31 GenericGrowableArray::GenericGrowableArray(int initial_size, int initial_len, GrET* filler, bool c_heap) {
           32 _len = initial_len;
           33 _max = initial_size;
           34 assert(_len >= 0 && _len <= _max, "initial_len too big");
           35 _arena = (c_heap ? (Arena*)1 : NULL);
           36 if (on_C_heap()) {
           37 _data = NEW_C_HEAP_ARRAY(GrET*, _max);
           38 } else {
           39 _data = NEW_RESOURCE_ARRAY(GrET*, _max);
           40 }
           41 for (int i = 0; i < _len; i++) _data[i] = filler;
           42 #ifdef ASSERT
           43 if (!on_C_heap()) {
           44 _nesting = Thread::current()->resource_area()->nesting();
           45 }
           46 #endif
           47 }
            ...
          222 void GenericGrowableArray::clear_and_deallocate() {
          223 assert(on_C_heap(),
          224 "clear_and_deallocate should only be called when on C heap");
          225 clear();
          226 if (_data != NULL) {
          227 FreeHeap(_data);
          228 _data = NULL;
          229 }
          230 }

        However, there is no call for clear_and_deallocate() before _env_thread_states is discarded
        in destructor, ~JvmtiThreadState().

          [hotspot/src/share/vm/prims/jvmtiThreadState.cpp]
           69 JvmtiThreadState::~JvmtiThreadState() {
            ...
           79 int ec = env_count();
           80 assert(ec == JvmtiEnvBase::env_count(), "Should be one JvmtiEnvThreadState per environment");
           81 for (int i = 0; i < ec ; ++i) {
           82 JvmtiEnvThreadState *ets = _env_thread_states->at(i);
           83 _env_thread_states->at_put(i, NULL);
           84 delete ets;
           85 }
           86 FreeHeap(_env_thread_states);
           87 _env_thread_states = NULL;

        So, every time JvmtiThreadState is created, which is, application creates threads, memory will leak.

              vchoudhaorcl Vaibhav Choudhary (Inactive)
              tbaba Tadayuki Baba (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: