内存沙盒

5
Java本来不应该存在内存泄漏问题,但仍有可能出现。当我的程序出现内存泄漏时,我可以修复它(希望如此)。但当第三方包存在内存泄漏问题时,我能做的事情很少,除了不使用该包。
还有其他解决方案吗?我喜欢沙盒的想法。你可以在某个区域内随意操作,而且“实际上”无法影响到盒子外的其他内容。是否有办法在Java中创建这样的内存使用沙盒?想象一下=创建一个内存使用沙盒,允许某些包做它们该做的事情,然后获取结果并删除此沙盒及其留下的任何垃圾!没有GC的麻烦,也没有清理或释放内存的问题。只需删除并忘记即可。
有办法这样做吗?
1个回答

1
最好的方法是启动另一个JVM,通过socket进行通信,完成后杀死JVM。
讨论一下是否可以在同一个JVM中对其进行沙盒处理会很有趣。
当你使用完第三方库并且不再引用该库中的任何对象时,还可能存在哪些垃圾?
1.他们的类 - 即使您没有引用它们中的任何一个,如果它们由与您的代码相同的类加载器加载,则这些类将持久存在。它们的静态字段可能引用更多的残留数据,等等。
2.ThreadLocal - 它可能设置了一些线程本地变量,并且没有清除它们。
3.Thread - 它可能已经创建了一些持久的线程。
4.在某个全局位置 - 例如System.setProperty() - 它将保留在那里。
因此,总体而言,这可能很困难。
但是,我们可以使用单独的类加载器和单独的线程来执行第三方库,这种策略可以在大多数情况下卸载第三方创建的所有垃圾。
有现成的工具可以做到这一点吗?我对此并不太了解。我有一些实现热重载服务器的经验,并且我有一些可用于此目的的实用类。例如:
// wrap 3rd party code, expose it as some java.*.* interface
public class MyWrapper implements Callable<String>
{
    @Override 
    public String call()
    {
        return ThirdParty.query(..);
    }
}



HotReloader hot = new HotReloader();
Callable<String> func = (Callable<String>)hot.getAppInstance("pkg.MyWrapper");
String result = func.call();
// then dereference `hot` and `func`

请查看HotReloader


这是个好主意,但有点贵。你能想象为每个数据库请求启动一个新的JVM吗?我曾经在JavaOne会议上参加了Plumbr的演示,“我打赌你有内存泄漏”,他们的一些例子是关于标准数据库驱动程序中的内存泄漏。如果我没记错的话,那是MySql。 - Izold Tytykalo
你可以使用 ClassLoaders 来隔离问题类。然后,为了清理库所使用的任何内存,只需删除所有对其类和加载器的引用即可。你还可以使用单独的 ThreadGroup 来隔离库线程,从而轻松地终止它们。 - Smith_61
@bayou.io 这是真的。在我能想到的大多数情况下都可以工作,但是如果不知道库的类型,很难想出完美的解决方案。 - Smith_61
@bayou.io - 很好的想法。数据库只是一个例子。但如果这样的机制存在(处理所有复杂性),那将是很棒的。不需要手动操作ClassLoader、Threads等。希望有一些简单的语法(最好像try/catch块或事务),可以尝试至少清除所有已使用的内存。 - Izold Tytykalo
@IzoldTytykalo - 那会很酷。然而,内存管理可能是JVM最大的任务;在一个JVM中创建两个内存区域可能与创建两个JVM并没有太大的区别... - ZhongYu
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接