锁定老帖子 主题:关于性能优化
精华帖 (2) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2010-11-17
最后修改:2010-11-17
ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
+1 需要区分清楚代码上的不使用(不再持有引用)和业务上的不使用(不需要再使用的信息) C++更多是前一种产生问题 Java更多是后一种产生问题 |
|
返回顶楼 | |
发表时间:2010-11-17
flysnowxf 写道 ironsabre 写道 现在设我是被Cache住的一个小对象,我就是这个对象,那么我的身份怎么定义?
A) 我是一个Cache住的有用的对象,我能提高访问效率。 B) 我是一个被泄漏掉的垃圾,我是垃圾。 我是A还是B,谁说了算,按什么标准执行? 因为程序是你自己写的,你当然知道哪些数据是垃圾数据。比如用户session放在cache里边,用户再一次登录,以前这个session就完全没有用了。如果不去清除,很明显的结果是内存会被占光。 你这样就把认定标准和具体的业务挂上钩了,总之这个跟Stack里的泄陋是两个性质完全不同的东西。 我觉得如果把两个完全不同的东西叫一个名字的话,是不对的。 |
|
返回顶楼 | |
发表时间:2010-11-17
最后修改:2010-11-17
ironsabre 写道 effective java中的这段代码,也不一定就有内存泄露。比如push elements[3]=e1,然后pop elements[3],e1已经被栈弹出,不过还是被引用着,等下次push elements[3]=e2的时候,e1就没有被引用了,可以被回收。
不管是程序不能访问,还是你自己认为是过期了,这部分数据归根结底都是垃圾数据,占着茅坑不拉屎,不删除了还留着干吗?难道等内存占了4g、8g的,老板问了,怎么这么大,你难道还解释说,这些数据还可以被访问的。。。 ----------------------------------------------- 需要分清我能删除还是我已经无法删除。 如果JDK里给你的Stack就是effective java里的这段,那么你在用的时候,你对很多已经垃圾了的对象是无能为力的,你很无助,你什么都做不了。我认为这种才算泄漏了。 而如果你用的是一个功能正常的HashMap,你是可以去删除你不想要的东西的。 这两种完全不一样。一种你能,一种你不能。 我希望你回答这个问题: 现在设我是被Cache住的一个小对象,我就是这个对象,那么我的身份怎么定义? A) 我是一个Cache住的有用的对象,我能提高访问效率。 B) 我是一个被泄漏掉的垃圾,我是垃圾。 我是A还是B,谁说了算,按什么标准执行? 回答的问题在上边。 你现在的思维是,能删除的就不是内存泄露了,不能删除的才是。我觉得更合理的理解是,出现内存泄漏是因为没有意识造成的。只要你没有意识到这个操作可能会造成内存占用越来越多,就算是内存泄漏了。 引用 如果JDK里给你的Stack就是effective java里的这段,那么你在用的时候,你对很多已经垃圾了的对象是无能为力的,你很无助,你什么都做不了。
没有什么事情是做不了的,我会这么收拾它: for() {push elements[i]=null;} for() {pop elements[i];} 很多时候,你都不知道它会造成内存泄漏。所以这才是关键,至于怎么做,都会有解决的办法。 |
|
返回顶楼 | |
发表时间:2010-11-17
ouchxp 写道 ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
+1 需要区分清楚代码上的不使用(不再持有引用)和业务上的不使用(不需要再使用的信息) C++更多是前一种产生问题 Java更多是后一种产生问题 这样就清楚了,我怎么就没想到这样表达呢。 其实我一直想说的是,在Java里新手想要产生前一种问题不是一件容易的事情。 但下面很多人用很容易产生了后一种问题来反驳我。 |
|
返回顶楼 | |
发表时间:2010-11-17
ironsabre 写道 ouchxp 写道 ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
+1 需要区分清楚代码上的不使用(不再持有引用)和业务上的不使用(不需要再使用的信息) C++更多是前一种产生问题 Java更多是后一种产生问题 这样就清楚了,我怎么就没想到这样表达呢。 其实我一直想说的是,在Java里新手想要产生前一种问题不是一件容易的事情。 但下面很多人用很容易产生了后一种问题来反驳我。 对你认为后一种 你不是问题,那是你自己的认为,你认为是正常的,如果在别人的系统中这样是不正常的,所以即使cache 也是有时效的,所以人家反驳你,因为你没亮出你的前提条件:“我的超级缓存,可以保存世界上一切的数据,是正常的” |
|
返回顶楼 | |
发表时间:2010-11-17
ironsabre 写道 ouchxp 写道 ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
+1 需要区分清楚代码上的不使用(不再持有引用)和业务上的不使用(不需要再使用的信息) C++更多是前一种产生问题 Java更多是后一种产生问题 这样就清楚了,我怎么就没想到这样表达呢。 其实我一直想说的是,在Java里新手想要产生前一种问题不是一件容易的事情。 但下面很多人用很容易产生了后一种问题来反驳我。 java有垃圾回收这东西,不用的对象不需要管,所以像c++需要手动delete的问题基本不会出现。java出现内存问题,很多时候都是容器使用不当造成的。 |
|
返回顶楼 | |
发表时间:2010-11-17
最后修改:2010-11-17
首先有一点很明确,内存泄漏是指内存空间得到释放,其次是有效释放还是无法释放。
关于HashMap其实没什么好讨论的,还是一句话,这是封装的问题。如: public Stack{ private HashMap map; public add(String,Object); public clear(); } 我想谁都会对其中的HashMap无语的。 其次是到底是指无法释放的内存才算泄漏还是没有有效释放的内存就算泄漏? 我认为是没有释放的内存统统都属于泄漏,很简单。如果你释放了,说明就没泄漏了。 要说明的是,泄漏在java中不是什么很特别的事,我认为更不可能出现什么无法释放内存的事,程序只要稍微变动,内存泄漏就没了,这只不是程序员没能考虑充分时出现的一个bug。 很明显,上面的程序要出现问题时,谁都会改动一下WeakHashMap,或者增加一个delete方法。 effect java中例子也是一样。 |
|
返回顶楼 | |
发表时间:2010-11-17
flysnowxf 写道 ironsabre 写道 effective java中的这段代码,也不一定就有内存泄露。比如push elements[3]=e1,然后pop elements[3],e1已经被栈弹出,不过还是被引用着,等下次push elements[3]=e2的时候,e1就没有被引用了,可以被回收。
不管是程序不能访问,还是你自己认为是过期了,这部分数据归根结底都是垃圾数据,占着茅坑不拉屎,不删除了还留着干吗?难道等内存占了4g、8g的,老板问了,怎么这么大,你难道还解释说,这些数据还可以被访问的。。。 ----------------------------------------------- 需要分清我能删除还是我已经无法删除。 如果JDK里给你的Stack就是effective java里的这段,那么你在用的时候,你对很多已经垃圾了的对象是无能为力的,你很无助,你什么都做不了。我认为这种才算泄漏了。 而如果你用的是一个功能正常的HashMap,你是可以去删除你不想要的东西的。 这两种完全不一样。一种你能,一种你不能。 我希望你回答这个问题: 现在设我是被Cache住的一个小对象,我就是这个对象,那么我的身份怎么定义? A) 我是一个Cache住的有用的对象,我能提高访问效率。 B) 我是一个被泄漏掉的垃圾,我是垃圾。 我是A还是B,谁说了算,按什么标准执行? 回答的问题在上边。 你现在的思维是,能删除的就不是内存泄露了,不能删除的才是。我觉得更合理的理解是,出现内存泄漏是因为没有意识造成的。只要你没有意识到这个操作可能会造成内存占用越来越多,就算是内存泄漏了。 引用 如果JDK里给你的Stack就是effective java里的这段,那么你在用的时候,你对很多已经垃圾了的对象是无能为力的,你很无助,你什么都做不了。
没有什么事情是做不了的,我会这么收拾它: for() {push elements[i]=null;} for() {pop elements[i];} 很多时候,你都不知道它会造成内存泄漏。所以这才是关键,至于怎么做,都会有解决的办法。 我改一下Stack,加上禁止push进来null元素。然后呢。没办法了。 这样来来回回是没意思的,我也不是说我认识的就是对,我只是想分清楚这两种是不一样的东西。有必要加以分别。 |
|
返回顶楼 | |
发表时间:2010-11-17
flysnowxf 写道 ironsabre 写道 ouchxp 写道 ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
+1 需要区分清楚代码上的不使用(不再持有引用)和业务上的不使用(不需要再使用的信息) C++更多是前一种产生问题 Java更多是后一种产生问题 这样就清楚了,我怎么就没想到这样表达呢。 其实我一直想说的是,在Java里新手想要产生前一种问题不是一件容易的事情。 但下面很多人用很容易产生了后一种问题来反驳我。 java有垃圾回收这东西,不用的对象不需要管,所以像c++需要手动delete的问题基本不会出现。java出现内存问题,很多时候都是容器使用不当造成的。 如果想反驳我,请举一下新手经常容易使用不当的例子。 注:新手是没多少机会去自己写一个Stack之类的,他们主要是实现业务,至少我没发现平时在实现业务操作的时候,有需要特别注意才能不泄漏的情况发生。 注意:我的反对的上前面一位兄弟的观点--他认为:新手经常容易造成泄漏。 |
|
返回顶楼 | |
发表时间:2010-11-17
dsjt 写道 ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 String str ="aaa" + "bbb" +"ccc" + "ddd"; StringBuilder sb = new StringBuilder(); sb.append("aaa"); sb.append("bbb"); sb.append("ccc"); sb.append("ddd"); String str = sb.toString(); 哪种效率高? 答案是第一种. 对于新手来说想优化很容易适得其反. 反编译看一下就知道为什么了. 我们项目经理不让用第一种 第一种写法它就是一个对象,它有一个字符串池的概念 而String += xx; 就不是字符串池的概念了,二者定义不同 |
|
返回顶楼 | |