Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6751861
Votes 0
Synopsis Memory leak occurs in JVMTI(jdk5.0u16)
Category hotspot:jvmti
Reported Against
Release Fixed 5.0u18-rev(b03), 5.0u19(b01) (Bug ID:2174433)
State 10-Fix Delivered, bug
Priority: 3-Medium
Related Bugs 6469701 , 6751862
Submit Date 24-SEP-2008
Description
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.
Posted Date : 2008-09-24 06:15:03.0
Work Around
N/A
Evaluation
The bug description does not mention if the customer has tried jdk6 but the issue should already been fixed via the changes for the more general problem that was 6306746. Furthermore, this code was subsequently replaced in jdk6 but the changes for 6369191 and 6452240.
Posted Date : 2008-09-24 10:37:15.0
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang