WeakReference如字面意思,弱引用, 当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果这时GC运行, 那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收。
作者:BrightLoong
链接:https://www.jianshu.com/p/964fbc30151a
使用背景:
弱引用对象常用于对象在内存中生命周期短,且占空间,在本次异常发生的对象是公司封装的HttpRequest弱引用对象
public HttpRequest getRequest() {
return (HttpRequest)this.httpRequestRef.get();
}
private WeakReference<HttpRequest> httpRequestRef
在业务逻辑中需要根据请求参数操作不同的分库,所以在Request对象中setAttribute有具体的分库index
然后在接口请求时启动另外一个线程执行任务,在线程中获取Request对象设置分库index
getRequestContext().setVaule(contextKey, value);
然后错误发生了,由于Request是弱引用对象,在另起线程时,如果发生GC,(HttpRequest)this.httpRequestRef.get();就会报空指针异常,由于在测试环境没有发生GC,导致这个BUG上到生产环境,百度一圈,然后再测试环境任务线程启动马上手动System.gc(),果然100%复现。
解决方法:
然后,在任务线程中传入Request对象,在线程中用强引用它,GC的时候就不会回收,空指针问题解决,但是会出现新问题,由于是线程池管理的线程,任务结束后,线程并没有结束,所以Request仍然不会被回收,可能会导致内存泄露,所以最后再释放一下对象就OK
public void clearCurrentRequestContext() {
contextHolder.remove();
}