Java 由于Lambda函数,JIT编译期间的本机内存峰值

Java 由于Lambda函数,JIT编译期间的本机内存峰值,java,performance,lambda,jvm,jit,Java,Performance,Lambda,Jvm,Jit,问题摘要: 有一个通用的java方法(比如methodCausingProblem(),其编译大小约为4KB)用于C2编译期间遇到一些本机内存峰值(约2GB)的所有请求。这种方法的奇怪之处在于lambda函数。在删除该可疑代码后,问题似乎得到了解决但我们仍然无法找到内存峰值的实际原因 调试路径: 在本机内存跟踪、探查器(perf和jem)、核心转储分析器(gdb和hsdb)的帮助下,我们能够识别出有问题的方法 publicstaticvoidmethodcausingproblem(){ //一

问题摘要:

有一个通用的java方法(比如methodCausingProblem(),其编译大小约为4KB)用于C2编译期间遇到一些本机内存峰值(约2GB)的所有请求。这种方法的奇怪之处在于lambda函数。在删除该可疑代码后,问题似乎得到了解决但我们仍然无法找到内存峰值的实际原因

调试路径:

在本机内存跟踪、探查器(perf和jem)、核心转储分析器(gdb和hsdb)的帮助下,我们能够识别出有问题的方法

publicstaticvoidmethodcausingproblem(){
//一些内容
DefaultValue obj=()->mymethod(“虚拟”);
字符串数据=obj.func();
//一些内容
}
公共静态字符串mymethod(字符串rel)引发异常{
返回rel;
}
公共静态接口默认值{
字符串func()引发异常;
}
详情如下:

使用探查器分析时,内存增长是在PhaseChaitin寄存器_分配期间,我们从相应的机器代码中找不到任何可疑的内容。据我们所知,这是基于溢出检查的一些优化,并决定寄存器分配

占用更多内存的本机堆栈跟踪:

_ZNK4Node13rematerializeEv + 0x20
    _ZN12PhaseChaitin5SplitEjP12ResourceArea + 0x9a0
    _ZN12PhaseChaitin17Register_AllocateEv + 0x9fd
    _ZN7Compile8Code_GenEv + 0x2bb
    _ZN7CompileC1EP5ciEnvP10C2CompilerP8ciMethodibbb + 0x1260
    _ZN10C2Compiler14compile_methodEP5ciEnvP8ciMethodi + 0x20c
    _ZN13CompileBroker25invoke_compiler_on_methodEP11CompileTask + 0xd46
    _ZN13CompileBroker20compiler_thread_loopEv + 0x657
    _ZN10JavaThread17thread_main_innerEv + 0xf1
    _ZL10java_startP6Thread + 0x132

编译事件:

<nmethod compile_id='32976' compiler='C2' level='4' entry='<hex>' size='444608' address='<hex>' relocation_offset='296' insts_offset='23920' stub_offset='251280' scopes_data_offset='266328' scopes_pcs_offset='341304' dependencies_offset='418600' handler_table_offset='418832' nul_chk_table_offset='443168' oops_offset='265072' method='<problematicMethod(arg1..argn)>' bytes='4191' count='1295' backedge_count='17962' iicount='1295' stamp='1042.504'/>

--编辑--

我们的应用程序中有许多lambda函数,但只有在这个地方出现了问题。我们希望在这种方法中进行更深入的挖掘,以确定实际问题,从而在将来解决此类问题

有更深入地调试它的想法吗

--更新--


只有在受影响方法的特定点调用lambda方法时,才会发生本机内存增长

我没注意到这里有问号。这看起来更像是一个bug报告,但堆栈溢出不是OpenJDK bugtracker。对不起。已经编辑了我的问题,现在请检查@使用4K字节码的apanginA方法非常庞大-您是否尝试过将其拆分为多个方法?什么是虚拟机版本?使用jemalloc运行JVM时,内存占用是否仍然会增加很多?请尝试减少
-XX:MaxNodeLimit
-XX:liveNodeCountInLiningCuttop
。感谢@apangin,将受影响的方法一分为二时不会出现问题,并且在减少MaxNodeLimit时(在活动范围拆分期间跳过编译)也不会出现问题(没有方法拆分)。但我想知道lambda函数是否创建了更多节点?是否可以在编译期间打印方法的节点大小?是:
-XX:+UnlockDiagnosticVMOptions-XX:+LogCompilation
。然后在编译日志中查找