don*_*bes 6 java recursion serialization non-recursive
我们从Java的序列化库中获取StackOverflowErrors.问题是默认的序列化实现是递归的,其深度仅受通过引用网络的最长路径的限制.
我们意识到我们可以覆盖默认方法,但是我们在项目中有数百个连接丰富的类,所以我们对覆盖方法并不热衷.如果存在非递归的通用解决方案(或者至少将递归从堆栈移动到堆),我们会更感兴趣.
我搜索了这个话题,发现只有很多人痛苦地抱怨同样的事情,但大多数这些抱怨来自很多年前.情况有所改善吗?如果没有,我们写一个通用的实现,你有什么建议吗?我们假设有一些原因(对我们来说还不明显)为什么没有人破解这个坚果.从理论上讲,做"正确"听起来应该是可行的.
小智 2
不久前我遇到了这个问题。对于连接丰富的类,即使您能够在没有堆栈溢出的情况下完成序列化,序列化也会非常慢。当我们解决这个问题时,我们有一些类,所以我们只是创建了自己的序列化格式,将数据打包到一组整数对象 id 中,每个字段都有整数字段 id ,并通过一系列对象 id 描述它们的连接、字段 id、其他对象 id 映射。这种自定义方法非常快并且占用内存极少,但只有在您想要序列化一小组类时才真正有效。
一般情况要困难得多,并且对丰富连接的类的序列化的需求并不那么强烈,所以我猜这就是为什么没有人解决它的原因。
不过,您基本上已经解决了这个问题,您总是需要一个等于深度优先搜索树的最大高度的堆栈深度,因此只要您的图比该深度更深,您就会遇到堆栈溢出。从根本上来说,这是一个递归问题,因此您要么需要使用递归,要么需要通过将堆栈分配移动到放置在堆上的 Stack 对象来使用假递归。我会看一下 OpenJDK 的实现:
您已经有一个 DebugTraceInfoStack,我将为您正在编写的当前对象创建第二个 Stack 字段,并更改 writeObject0 方法以将对象推入堆栈,如下所示:
stack.push(obj);
while(!stack.empty()) {
obj = stack.pop();
...
Run Code Online (Sandbox Code Playgroud)
然后你只需将所有调用更改为 writeObject0(x); 到 stack.push(x);。递归和迭代之间的简单、标准转换,除了该类几乎有 2500 行,并且可能存在大量陷阱。
如果你最终构建了它,我建议将 at 作为 java 的下一个版本的补丁提交,因为它会很有用,比如用于深度对象图的 IterativeObjectOutputStream。
| 归档时间: |
|
| 查看次数: |
1928 次 |
| 最近记录: |