当前位置: 首页 > article >正文

openjdk17 jvm 大对象 内存分配 在C++源码体现

##java大对象数组,计算260000长度引用类型数组大概占用1M左右空间

import java.util.ArrayList;
import java.util.List;

public class OutOfMemoryTest {

    public static void main(String[] args) {
        List<MiBigObject> miBigObjects = new ArrayList<>(260000);
        int length=0;
        while(true) {
            MiBigObject miBigObject = new MiBigObject();
            miBigObjects.add(miBigObject);
            System.out.println(length++);
        }
    }

}

public class MiBigObject {
}

##C++分配大对象数组内存GDB堆栈

#0  G1CollectedHeap::attempt_allocation_humongous (this=0x7ffff00453d0, word_size=130002) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:826
#1  0x00007ffff61d65ee in G1CollectedHeap::mem_allocate (this=0x7ffff00453d0, word_size=130002, gc_overhead_limit_was_exceeded=0x7ffff7bfe570)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:372
#2  0x00007ffff6779bf8 in MemAllocator::allocate_outside_tlab (this=0x7ffff7bfe5d0, allocation=...)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/shared/memAllocator.cpp:258
#3  0x00007ffff677a023 in MemAllocator::mem_allocate (this=0x7ffff7bfe5d0, allocation=...) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/shared/memAllocator.cpp:358
#4  0x00007ffff677a068 in MemAllocator::allocate (this=0x7ffff7bfe5d0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/shared/memAllocator.cpp:365
#5  0x00007ffff6019669 in CollectedHeap::array_allocate (this=0x7ffff00453d0, klass=0x100058458, size=130002, length=260000, do_zero=true, __the_thread__=0x7ffff0028920)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/gc/shared/collectedHeap.inline.hpp:41
#6  0x00007ffff6344a7c in InstanceKlass::allocate_objArray (this=0x100041040, n=1, length=260000, __the_thread__=0x7ffff0028920)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/oops/instanceKlass.cpp:1349
#7  0x00007ffff685c14e in oopFactory::new_objArray (klass=0x100041040, length=260000, __the_thread__=0x7ffff0028920)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/memory/oopFactory.cpp:122
#8  0x00007ffff6368710 in InterpreterRuntime::anewarray (current=0x7ffff0028920, pool=0x7fffd99038f0, index=7, size=260000)
    at /home/yym/openjdk17/jdk17-master/src/hotspot/share/interpreter/interpreterRuntime.cpp:266
#9  0x00007fffe1023e51 in ?? ()
#10 0x00007fffe1023dc2 in ?? ()
#11 0x00000000ffa167e0 in ?? ()
#12 0x00007ffff7bfe730 in ?? ()
#13 0x00007fffd9908ed2 in ?? ()
#14 0x00007ffff7bfe790 in ?? ()
#15 0x00007fffd9aced80 in ?? ()
#16 0x0000000000000000 in ?? ()

##C++源码

HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) {
  ResourceMark rm; // For retrieving the thread names in log messages.

  // The structure of this method has a lot of similarities to
  // attempt_allocation_slow(). The reason these two were not merged
  // into a single one is that such a method would require several "if
  // allocation is not humongous do this, otherwise do that"
  // conditional paths which would obscure its flow. In fact, an early
  // version of this code did use a unified method which was harder to
  // follow and, as a result, it had subtle bugs that were hard to
  // track down. So keeping these two methods separate allows each to
  // be more readable. It will be good to keep these two in sync as
  // much as possible.

  assert_heap_not_locked_and_not_at_safepoint();
  assert(is_humongous(word_size), "attempt_allocation_humongous() "
         "should only be called for humongous allocations");

  // Humongous objects can exhaust the heap quickly, so we should check if we
  // need to start a marking cycle at each humongous object allocation. We do
  // the check before we do the actual allocation. The reason for doing it
  // before the allocation is that we avoid having to keep track of the newly
  // allocated memory while we do a GC.
  if (policy()->need_to_start_conc_mark("concurrent humongous allocation",
                                        word_size)) {
    collect(GCCause::_g1_humongous_allocation);
  }

  // We will loop until a) we manage to successfully perform the
  // allocation or b) we successfully schedule a collection which
  // fails to perform the allocation. b) is the only case when we'll
  // return NULL.
  HeapWord* result = NULL;
  for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
    bool should_try_gc;
    bool preventive_collection_required = false;
    uint gc_count_before;


    {
      MutexLocker x(Heap_lock);

      size_t size_in_regions = humongous_obj_size_in_regions(word_size);
      preventive_collection_required = policy()->preventive_collection_required((uint)size_in_regions);
      if (!preventive_collection_required) {
        // Given that humongous objects are not allocated in young
        // regions, we'll first try to do the allocation without doing a
        // collection hoping that there's enough space in the heap.
        result = humongous_obj_allocate(word_size);
        if (result != NULL) {
          policy()->old_gen_alloc_tracker()->
            add_allocated_humongous_bytes_since_last_gc(size_in_regions * HeapRegion::GrainBytes);
          return result;
        }
      }

      // Only try a GC if the GCLocker does not signal the need for a GC. Wait until
      // the GCLocker initiated GC has been performed and then retry. This includes
      // the case when the GC Locker is not active but has not been performed.
      should_try_gc = !GCLocker::needs_gc();
      // Read the GC count while still holding the Heap_lock.
      gc_count_before = total_collections();
    }

    if (should_try_gc) {
      GCCause::Cause gc_cause = preventive_collection_required ? GCCause::_g1_preventive_collection
                                                              : GCCause::_g1_humongous_allocation;
      bool succeeded;
      result = do_collection_pause(word_size, gc_count_before, &succeeded, gc_cause);
      if (result != NULL) {
        assert(succeeded, "only way to get back a non-NULL result");
        log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT,
                             Thread::current()->name(), p2i(result));
        size_t size_in_regions = humongous_obj_size_in_regions(word_size);
        policy()->old_gen_alloc_tracker()->
          record_collection_pause_humongous_allocation(size_in_regions * HeapRegion::GrainBytes);
        return result;
      }

      if (succeeded) {
        // We successfully scheduled a collection which failed to allocate. No
        // point in trying to allocate further. We'll just return NULL.
        log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate "
                             SIZE_FORMAT " words", Thread::current()->name(), word_size);
        return NULL;
      }
      log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT "",
                           Thread::current()->name(), word_size);
    } else {
      // Failed to schedule a collection.
      if (gclocker_retry_count > GCLockerRetryAllocationCount) {
        log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating "
                               SIZE_FORMAT " words", Thread::current()->name(), word_size);
        return NULL;
      }
      log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name());
      // The GCLocker is either active or the GCLocker initiated
      // GC has not yet been performed. Stall until it is and
      // then retry the allocation.
      GCLocker::stall_until_clear();
      gclocker_retry_count += 1;
    }


    // We can reach here if we were unsuccessful in scheduling a
    // collection (because another thread beat us to it) or if we were
    // stalled due to the GC locker. In either can we should retry the
    // allocation attempt in case another thread successfully
    // performed a collection and reclaimed enough space.
    // Humongous object allocation always needs a lock, so we wait for the retry
    // in the next iteration of the loop, unlike for the regular iteration case.
    // Give a warning if we seem to be looping forever.

    if ((QueuedAllocationWarningCount > 0) &&
        (try_count % QueuedAllocationWarningCount == 0)) {
      log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words",
                             Thread::current()->name(), try_count, word_size);
    }
  }

  ShouldNotReachHere();
  return NULL;
}


http://www.kler.cn/a/421060.html

相关文章:

  • RouterOS ROSV7 基于域名的分流实现
  • 构建短视频矩阵生态体系开发分享
  • 卷积网络和残差网络
  • 【AI系统】Ascend C 语法扩展
  • 家政小程序开发,打造便捷家政生活小程序
  • C# 定时通讯的高速串口的编程框架
  • C++(六)
  • 手机设置了卡2上网,卡1禁止上网,但是卡1还是会偷偷跑流量,这是什么情况???
  • 【HTTP】HTTP协议
  • 嵌入式蓝桥杯学习1 电量LED
  • Kylin Server V10 下基于Kraft模式搭建Kafka集群
  • Leetcode 每日一题 383.赎金信
  • D86【python 接口自动化学习】- pytest基础用法
  • 《Spring Boot 整合 Avro 与 Kafka》
  • C++ 简介
  • 恼人的MAVEN,继续报 xx is present in the local repository, but
  • 第十七届山东省职业院校技能大赛 高职组“信息安全管理与评估”比赛通知
  • 7、硬盘品牌分类介绍:西数 - 计算机硬件品牌系列文章
  • java执行规则引擎
  • LeetCode763. 划分字母区间(2024冬季每日一题 23)