[讨论] 能否根据引用计数器来查看堆中对象的使用情况
haoweishow
2011-12-14
有些对象加载到内存中,可能根本就不会被使用。例如一个list里面,加载了100个数据,但只有那么几个在被频繁的使用,而其他的就根本没有使用过。
能否根据垃圾回收的引用计数器来发现这些未用的对象呢? 或者有没有其他方法,发现一些耗着资源(占着内存),但从未被使用的对象。 |
|
RednaxelaFX
2011-12-14
对GC来说“从根集合出发有活引用能到到”的对象就是活对象,那些引用的存在本身就是“使用”。你所想像的“使用”跟GC所认为的“使用”不是同一个概念。
只要某个对象不能从根集合出发通过活引用到达,那GC就会认为这个对象是死的,随后GC就回收了。如果你所想的使用跟GC所用的是同一个概念,那什么也不用做。但显然你想要的不是这个。 常见的JVM都不使用引用计数的方式来实现Java heap的自动内存管理。即便使用引用计数,“有引用”跟“被使用”对你来说仍然是两个概念,所以没用。 在这种想定场景里想省内存一般要做的是lazy加载数据,而不是一开始就把所有数据加载进来等着GC把“没使用的数据”清理掉。有需要的话可以再加上用LRU容器来保存最近活跃的数据以便控制内存使用量。 另一个解决方案就是使用弱引用,例如SoftReference或者WeakReference。详细请再去查别的资料。弱引用的陷阱多多,请小心使用。 ========================================= 如果在VM里加些拦截代码的话,Java对象的“使用”(这里指的是真的去读写对象内的字段)应该是有办法跟踪的。但我能想到的办法开销都很大,不实用;本来设置内存的watchpoint也可以,但有些系统上watchpoint只能设置很少量的个数,所以也不实用。 |
|
haoweishow
2011-12-14
RednaxelaFX 写道 在这种想定场景里想省内存一般要做的是lazy加载数据,而不是一开始就把所有数据加载进来等着GC把“没使用的数据”清理掉。有需要的话可以再加上用LRU容器来保存最近活跃的数据以便控制内存使用量。
我的想法是 不管是是启动加载还是lazyLoad,数据总是要加载的,问题出现在加载后数据占用的内容。 如果使用LRU容器的话,对于一个简单的功能来说太过麻烦了。 目前碰到的场景是系统配置文件越来越多,各种各样的功能导致越来越庞大,时间久远,很多功能已经找不到文档。想精简系统 从对象使用的角度去发现冗余数据。 因为在一次打印gc信息的时候,通过这个命令参数-XX:+PrintClassHistogramBeforeFullGC发现old区一个对象的实例超多,而这些对象在这个系统中就不会使用到(这个是靠经验判断) |