1.递归问题
public class Test2 { public static void main(String args[]) { System.out.print(test(1)); } private static ExecutorService exec = Executors.newFixedThreadPool(1); /** * 初步理解递归是因为方法返回阻塞,造成方法堆积,异步可用解决 * EXEC 方式执行,虽然只有一个线程,但是这样做不耽误方法返回,测试不会造成OOM * @param i * @return */ private static int test( int i){ i++; if(i<100000){ // new Thread(new Runnable() { // @Override // public void run() { // test(2); // } // }).start(); exec.execute(new Runnable() { @Override public void run() { test(2); } }); } return i; } }
解读:正在情况下,递归多了会造成OOM,通过exec.execute执行不至于耽误上个方法返回,经过测试,可用有效避免OOM.
2.通道的频繁重连可能最终导致OOM
问题解读,通过分析 channel相关的 hashcode和 channeled等信息,确认重连之后,channel是一个全新的
channel对象,所以老的channel对象需要回收和关闭掉,否则会造成多channel链接现象(实验证明),经过测试,可用避免OOM问题
private void recycleChannel(){ if(mChannel != null){ Channel channel = mChannel; channel.deregister(); channel.close(); KidSocketLog.addTag("mChannel卸载流程执行"); } }
3.hot observale memory leak
this.kidObservable = Observable.fromEmitter(new Action1<Emitter<KidSocketData>>() { @Override public void call(final Emitter<KidSocketData> emitter) { final KidSocketCallBack kidSocketCallBack = new KidSocketCallBack() { @Override public void socketMessageArrived(SocketMessageBean messageBean) { KidSocketLog.addTag("socketMessageArrived:"+messageBean==null?"messageBean=null":messageBean.getDataMessage()); emitter.onNext(messageBean); } }; emitter.setCancellation(new Cancellable() { @Override public void cancel() throws Exception { KidSocketLog.addTag("kidSocketCallBackManager unregister kidSocketCallBack"+kidSocketCallBack.toString()); kidSocketCallBackManager.unRegister(kidSocketCallBack); } }); KidSocketLog.addTag("kidSocketCallBackManager register kidSocketCallBack"+kidSocketCallBack.toString()); kidSocketCallBackManager.register(kidSocketCallBack); } }, Emitter.BackpressureMode.BUFFER);
红色部分是后来加的,否则会造成callback在取消订阅后依然存在,取消订阅后,就算callback 执行,订阅者
也不会收到,但是calback还存在是没有意义的,造成内存泄漏
4.多线程操作变量问题
public void receiveSocketMsg(SocketMessageBean socketMessageBean){ try { KidSocketLog.addTag("receiveSocketMsg执行"); if(kidSocketCallBackList != null){ List<KidSocketCallBack> operationKidSocketCallBackList = new ArrayList<KidSocketCallBack>(); operationKidSocketCallBackList.addAll(kidSocketCallBackList); KidSocketLog.addTag("operationKidSocketCallBackList size="+operationKidSocketCallBackList.size()); for (KidSocketCallBack kidSocketCallBack:operationKidSocketCallBackList){ kidSocketCallBack.socketMessageArrived(socketMessageBean); } }else { KidSocketLog.addTag("kidSocketCallBackList === null,不通过回调下发消息"); } }catch (Throwable e){ KidSocketLog.addTag("receiveSocketMsg 执行异常",e); } }为什么要把 callback新创建一个 List<KidSocketCallBack> operationKidSocketCallBackList呢,因为直接操作原始的list,原来的list可能东西被移除了,
我又在遍历,了能会导致线程并发问题