Car*_*eon 4 java sybase jvm hibernate out-of-memory
在启动时本地运行的应用程序(Spring,JPA Hibernate,Sybase 12,Webapp)消耗基于VisualVM的40MB 256MB堆空间.当我触发一个返回70,000多行(文本数据没有blob)的搜索时,堆空间图最多可以拍摄256MB并且会丢失内存.我已经通过使用setMaxResults(limit)解决了这个问题.但是,当我查询相同的数据,复制粘贴到文本文件并保存到文件系统时,我可以看到大小只有26MB的文本.
因此,实际上,216MB(从256-40)被从数据库加载文本26MB消耗量谁在占用190MB的时候出现内存不足的发生?也许这将是框架,但我不知道它如何消耗比实际加载的数据更多...
**再次注意我用setMaxResults(限制)解决了这个问题,我的问题不是该做什么,而是为什么,出于教育目的.
有些事情需要考虑:
您的操作系统可能使用每字符8位编码来存储文本文件.内部的Java字符串都以每字符16位编码,在那里加倍.
只有几位数的数字将被编码为文本而不是数字.例如,'1'是文本文件中的一个字节字符,但值为1的long是内存中大小的八倍.
hibernate会从SQL结果集中取值并将其映射到java对象上.它可能需要将结果集的内容包装/转换为您在映射中定义的类型.
如果每个实体的数据实际上很小并且有大量实体,那么对象开销大小与数据大小的比率显然会很高.
如果集合中包含小块数据,则集合的大小可以相对于数据快速累加.在极端的例子中,如果你有一个或两个字符串的LinkedList,那么只有每个16-32位实际数据的指针消耗192位.在数组列表中,指针指向16-32位数据仍然是64位.(当然假设是64位操作系统.)
你在hibernate中加载的每个对象都被"跟踪",以便在所谓的L1缓存中进行脏检查.对于具有少量数据的大量实体的数据大小,内部数据结构和用于执行此操作的工具确实会有相当多的开销.
-
因此,26MB的数据已经是java内存中的52MB数据,假设它是所有字符串,没有数字,没有日期,否则它会更大.
然后,如果它分成许多小块,700,000个小字符串而不是1,000个非常长的字符串,那么数据结构开销的大小是实际数据大小的三倍是完全合理的,可以轻松地推动你超过200MB.
| 归档时间: |
|
| 查看次数: |
309 次 |
| 最近记录: |