当启动本地运行的应用程序(春,JPA休眠时,Sybase 12的webapp)消耗的基础上VisualVM的256MB的堆空间40MB。 当我触发返回20000行(文本数据没有斑点)的堆空间图形拍摄到256MB,并引发内存搜索。 我以setMaxResults(极限)解决了这个。 然而,当我查询相同的数据,复制粘贴到一个文本文件并保存到文件系统中,我可以看到大小的文本只有26MB的价值。
因此,实际上,216MB(从256-40)被从数据库中, 谁是耗时的190MB的内存不足时加载文本26MB量消耗? 也许这将是框架,但我看不出它如何能消耗更多的不是被实际加载的数据...
*再次注意,我解决了这个与setMaxResults(限制),我的问题是不是做什么,而是为什么,教育目的。
有些事情要考虑:
你的操作系统可能使用每字符编码的8位来存储文本文件。 Java字符串在内部都编码的每个字符16位,右有翻倍的空间。
只有几个数字号码将被编码的小文本不是数字。 例如,“1”是在文本文件中的一个字节字符,但数值1是八倍大小的内存很长。
届时将有来自休眠重复值取出来的SQL结果集并将其映射到Java对象。 这可能需要包装/翻译结果集复制到您的映射定义的类型的内容。
如果你的数据,每个实体与大量实体实际上很小,那么物体开销大小的数据大小的比例显然会很高。
如果你有收藏小块的数据,集合的大小可以相对快速加起来的数据。 在极端的例子,如果你有一个或两个字符串的链表,这只是通过对实际数据的每16-32位指针消耗192bits。 在一个数组列表它仍然是64个比特用于指针指向数据的16-32比特。 (假设当然64位操作系统。)
每一个对象,你在休眠负载为“跟踪”在什么所谓的L1缓存脏检查。 这里确实可以相当多的开销用来此相对的数据大小大量小数据量的实体做内部数据结构和检测仪器。
-
因此,数据的26MB已经在Java内存数据的52MB,假设它是所有的字符串,没有数字,没有日期,这将是更大的,否则。
然后,如果它分割成许多小块70万个的小字符串,而不是1000级很长的,这是完全合理的数据结构开销的大小是实际数据的三倍大小,推你了200MB容易。
各种各样的事情。
让我们考虑,例如,你的行具有10个文本列,其表示为一个简单的Java Bean有10个字符串字段。
字符串中是否有4个字段:一个char [],和3个整数。
字符串被从对象,它具有1个INT后代,以及其类的引用。
在64位JVM,这些提法很可能是8个字节(但不是必须的,但我们会与坚持为参数的缘故)。
10文字串将具有一个char [10],以及3个整数,其各自是4个字节。
炭[10]是一个指针数组。 一个阵列具有跟踪其长度,这很可能另一个4个字节,并且它也是一个对象(因此类指针和另一个INT)加上数据。 但在Java字符被表示为UTF-16内部,每个字符的2个字节。 因此,对于10个字符的实际花费阵列24个字节。 并且参考该阵列是一个指针。
所以,单个的String实例是:8 + 4为对象,8 + 4 + 4 + 4为字符串本身,和8 + 4 + 20为实际的数据,或62个字节。
你的bean有10个字符串字段,以及扩展对象,所以8 + 4 +(10 * 8)。
所以,从数据库的单个行,100个字符的文本,是8 + 4 +(10 * 8)+,其等于712个字节(10×62)。
这些都不是完美的数字,我不会说明具体到阵列的存储方式,以及对象的引用可能不会在JVM 64B 8个字节。
但它给你所涉及的开销有所了解。 而这仅仅是你的原始数据。 如果您有存储在一个ArrayList那些行,那么,有70000 * 8只指向你的对象 - 560K只是结构。