最近发现游戏服产生了大量的Long临时对象,导致YGC的频率过高。
用Jprofiler调试了下,发现了大部分是从map的get()方法产生的(游戏里面有些线程会比较频繁的去一些map里面查询数据)
就像下面的例子:
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
public class GcTest {
public static Map<Long, String> map = new HashMap<Long, String>();
public static void main(String args[]) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
test1();
test2("a", "b", "c");
}
}, 100L, 100L);
}
public static void test1() {
long id = 12345678910L;
map.get(id);
System.out.println("test1");
}
public static void test2(String...params) {
System.out.println("test2");
}
}
首先map的key为Long类型,然而传给map.get()方法的参数却是普通的long,这时候java内部会先隐式的调用Long.valueOf(long),临时的产生了一个对应的Long对象,然后用它来去容器里面查询。
ps:对于 -128 <= x <= 127 这种比较小的数,java本身会做缓存,不会去new 一个Long对象
这个Long对象在查询完后,就没有引用了,一直呆在堆内存里,直到YGC发生时才回收
同样的,jdk1.5新增的方法动态参数,也会隐式的产生一个对应的数组对象
知道了问题所在就好办了,对于我的游戏来说,比较频繁的就是根据玩家的id去查询一些信息,只要把玩家的id从long改成Long,以后所有查询都通过这个唯一的Long对象来传送参数