我一直在遇到问题,确保我正在销毁的Spring应用程序上下文已经完全消失,并且无法看到该对象被垃圾收集。当我查看VisualVM中的实例时,我可以看到对上下文和它的bean工厂有很多未完成的引用,一旦上下文被关闭和销毁就会保留。这些都与bean工厂的初始设置有关(在AbstractApplicationContext的刷新方法期间),它使用各种bean后处理器等注册bean工厂和上下文。
bean工厂或应用程序上下文(甚至是可刷新的)上似乎没有任何方法可以删除对bean工厂的最低级别引用。结果是它似乎在泄漏内存,并且在某些情况下会阻止干净地重新创建上下文。
我问的是,我正在处理的软件可能会动态创建/销毁然后重新创建上下文(因为模块是动态加载和卸载的),并且上下文和bean工厂的剩余元素会导致问题使用诸如spring-data-jpa之类的组件(特别是将存储库接口绑定到存储库实现的代理)。
有没有人知道我可以干净地完全删除上下文和bean工厂而不必完全关闭最初创建它的VM的方法?
答案 0 :(得分:1)
最近再次研究过这个问题,我注意到我重写了上下文的new Vue({
components: {
'PulseLoader': PulseLoader
}
})
方法,以确保bean被完全销毁,但没有调用@Override
public boolean onTouch(View view1, MotionEvent event) {
final int X = (int) event.getRawX() - minusDisplayVal;
final int Y = (int) event.getRawY() - minusDisplayVal;
LinearLayout.LayoutParams layoutParamsSub = (LinearLayout.LayoutParams) view1
.getLayoutParams();
int _xDelta = 0;
int _yDelta = 0;
switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
_xDelta = X - layoutParamsSub.leftMargin;
_yDelta = Y - layoutParamsSub.topMargin;
break;
case MotionEvent.ACTION_UP:
_xDelta = X - layoutParamsSub.leftMargin;
_yDelta = Y - layoutParamsSub.topMargin;
break;
case MotionEvent.ACTION_POINTER_DOWN:
_xDelta = X - layoutParamsSub.leftMargin;
_yDelta = Y - layoutParamsSub.topMargin;
break;
case MotionEvent.ACTION_POINTER_UP:
_xDelta = X - layoutParamsSub.leftMargin;
_yDelta = Y - layoutParamsSub.topMargin;
break;
case MotionEvent.ACTION_MOVE:
layoutParamsSub.leftMargin = X - _xDelta;
layoutParamsSub.topMargin = Y - _yDelta;
if (layoutParamsSub.leftMargin < 0)// //for left
layoutParamsSub.leftMargin = 0;
if (layoutParamsSub.topMargin < 0)// ///for top
layoutParamsSub.topMargin = 0;
dataTv.setLayoutParams(layoutParamsSub);
break;
}
backgroudColor.invalidate();
return true;
}
方法,这意味着{ {1}} / doClose()
/ super.doClose()
和LiveBeansView.unregisterApplicationContext()
未被调用。
我添加了这个,并且(大多数)如果不是所有的上下文现在都被彻底销毁并且收集了垃圾。我将假设任何未被破坏的未完成的上下文更可能是我们自己的代码中带有悬空引用的问题。
答案 1 :(得分:0)
如果您在非Web应用程序环境中使用Spring的IoC容器;例如,在富客户端桌面环境中;您在JVM上注册了一个关闭钩子。这样做可确保正常关闭并在单例bean上调用相关的destroy方法,以便释放所有资源。当然,您仍然必须正确配置和实现这些destroy回调。
要注册一个关闭钩子,你应该调用在registerShutdownHook()
类上声明的AbstractApplicationContext
方法:
<强>代码强>
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class startup {
public static void main(final String[] args) throws Exception {
AbstractApplicationContext ctx
= new ClassPathXmlApplicationContext(new String []{"beans.xml"});
// add a shutdown hook for the above context...
ctx.registerShutdownHook();
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
}
答案 2 :(得分:0)
在上下文中调用destroy
并将null设置为引用应用程序上下文实例的所有变量:
AbstractApplicationContext context = new ClassPathXmlApplicationContext(new String []{"beans.xml"});
// ... do your stuff
context.destroy();
context = null;