集算器疑似内存泄漏 - finalize()
集算器版本:20230520
调用方式:远程计算即
通过 MAT 进行内存分析如下
finalize 方法被调用
finalize 方法 我理解的为了兜底 可是底层只有一个线程去负责这个操作 当并发查询的时候 肯定是赶不上 生成的速度的 很容易堆溢出
通过 jvisualVm 进行观察 拿到数据后大约要 2 分钟左右才进行了释放。
关于 finalize 方法的案例可以参考百度
https://www.cnblogs.com/wftop1/p/15021386.html
发现 jdk9 开始此方法已经弃用。
建议还是从程序上去显式的去释放资源 不要去期望这个 finalize 方法。
对应的执行的脚本语句:
==now()
=days@o(date(“1995-03-15”)) =date(“03/15/1995”)
/>mktsegment=c_mktsegment.pos@b(“BUILDING”)
=file(“/data/soft/esProc/file/Performance_Spl/CUSTOMER.ctx”).open().cursor@m (C_CUSTKEY;).fetch().keys@im(C_CUSTKEY)
=file(“/data/soft/esProc/file/Performance_Spl/ORDERS.ctx”).open().cursor@m (O_ORDERKEY,O_ORDERDATE,O_SHIPPRIORITY;O_ORDERDATE>date($B_ORDERDATE) && O_ORDERDATE
=file(“/data/soft/esProc/file/Performance_Spl/LINEITEM.ctx”).open().news@r (A5,O_ORDERKEY,sum(L_EXTENDEDPRICE*(1-L_DISCOUNT)):REVENUE,O_ORDERDATE,O_SHIPPRIORITY;L_SHIPDATE>B2)
=A6.fetch()
参数:
B_ORDERDATE:1995-03-25 00:00:00 E_ORDERDATE:1995-03-31 00:00:00
这个 spl 语句 估计不是最优的 我只是通过这个例子来说明 使用 finalize 的弊端而已 望理解。不用纠结这个执行语句的写法
具体的现象是什么样的呢?程序跑得慢,还是内存不够用崩溃了?
内存溢出了噻
内存 设置 最大堆 跟最小堆 都是 60g , 建议规避下 finalize 方法 ,几个月前就发现了一直没时间提
这是几个月前的
程序肯定跑的慢 外面看起来就跟死了一样 没反应
用的是什么时候的 jar 包?
20230520
看了你们最新的源代码 关键位置跟 20230520 是一样的
这应该是 jdk9 的机制改变导致,jdk8 应该没问题
jdk9 中 finalize()由专门的 FinalizerThread 执行,这个线程的优先级比 GC 低
大哥 我用的 jdk1.8
你可以看下 官网 对 finalize 的说明吧
看了下,jdk8 也是用 FinalizerThread,这样重载 finalize 确实会增大内存溢出的风险
你说的是哪个游标类?
目前有一些需要释放数据库连接或文件句柄的类重载了 finalize 方法用于关闭资源,这些类本身实例少,不会占用多少内存。
占用资源的类会被加入到资源管理器中,脚本执行完后会释放资源管理器中占用的资源。
比如文件游标,游标的数据被取完后会释放打开的文件,如果游标数据在脚本中没有取完,脚本又没有调用游标的 close 方法,
则在脚本执行完后,资源管理器会是否这个游标占用的文件。
重载 finalize 方法是为了防止有特殊情况出现导致资源管理器工作出现异常导致有些资源释放不掉。
com.scudata.dw.ComTable#finalize 目前看这个 finalize 里面的处理逻辑挺多的
类本身占用少 这个理解,重点在于 jdk 对 finalize 方法的处理机制,并发的时候 影响性能就会很明显, 我看 有些类里面重写 finalize 方法里面的逻辑也并不简单呀 比如:
com.scudata.dw.ComTable#finalize
兜底处理也是理解的关于这个兜底 能否利用 try-with-resource 进行一些等效的替换呢? 或者加一些前置判断 已经显示关了的不用重复关(不太清楚你们是不是早就做了)