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

Memory leak in G1 because G1RootProcessor doesn't have desctructor

XMLWordPrintable

    • gc
    • b81

        G1RootProcessor constructor allocate SubTasksDone object for _process_strong_tasks field(hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp):

        G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
            _g1h(g1h),
            _process_strong_tasks(new SubTasksDone(G1RP_PS_NumElements)),
            _srs(n_workers),
            _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
            _n_workers_discovered_strong_classes(0) {}

        SubTasksDone also allocate memory(hotspot/src/share/vm/gc/shared/workgroup.cpp):

        SubTasksDone::SubTasksDone(uint n) :
          _n_tasks(n), _tasks(NULL) {
          _tasks = NEW_C_HEAP_ARRAY(uint, n, mtInternal);
          guarantee(_tasks != NULL, "alloc failure");
          clear();
        }

        But G1RootProcessor doesn't have destructor which will destroy SubTasksDone object when G1RootProcessor will go out from the scope. This leads to the memory leak in the following places:
        hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp module:
        void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
        ...
            {
              G1RootProcessor root_processor(this, 1);
              root_processor.process_all_roots(&rootsCl,
                                               &cldCl,
                                               &blobsCl);
            }
        ...
        void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
        ...
          {
            G1RootProcessor root_processor(this, n_workers);
            G1ParTask g1_par_task(this, _task_queues, &root_processor, n_workers);
            // InitialMark needs claim bits to keep track of the marked-through CLDs.
            if (collector_state()->during_initial_mark_pause()) {
              ClassLoaderDataGraph::clear_claimed_marks();
            }

            // The individual threads will set their evac-failure closures.
            if (PrintTerminationStats) {
              G1ParScanThreadState::print_termination_stats_hdr();
            }

            workers()->run_task(&g1_par_task);
            end_par_time_sec = os::elapsedTime();

            // Closing the inner scope will execute the destructor
            // for the G1RootProcessor object. We record the current
            // elapsed time before closing the scope so that time
            // taken for the destructor is NOT included in the
            // reported parallel time.
          }
        ...

        hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp module:
        void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
                                            bool clear_all_softrefs) {
        ...
          {
            G1RootProcessor root_processor(g1h, 1);
            root_processor.process_strong_roots(&GenMarkSweep::follow_root_closure,
                                                &GenMarkSweep::follow_cld_closure,
                                                &follow_code_closure);
          }
        ...
        void G1MarkSweep::mark_sweep_phase3() {
        ...
          {
            G1RootProcessor root_processor(g1h, 1);
            root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
                                             &GenMarkSweep::adjust_cld_closure,
                                             &adjust_code_closure);
          }
        ...

              david David Lindholm (Inactive)
              ddmitriev Dmitry Dmitriev
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: