在你的类中使用装饰的OutputStream / InputStream字段 [英] Using decorated OutputStream/InputStream fields in your class

查看:166
本文介绍了在你的类中使用装饰的OutputStream / InputStream字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题起初看起来有点微不足道,但自从我开始实施这个以来,我遇到了一些奇怪的OutOfMemory问题。查看Java堆转储后,我知道内存泄漏与ObjectOutputStream变量有关。毫不费力,这里是代码:



在我的构造函数中,我设置了可以保存我的输入/输出流变量的字段变量。除此之外,我还创建了另外两组变量,用于在自定义对象上执行IO操作,然后执行纯原语操作:

  public SingleServer(Socket s,int maxThreads){
client = s;
serversCreated.incrementAndGet();
try {
is = client.getInputStream();
os = client.getOutputStream();
ois = new ObjectInputStream(is);
oos = new ObjectOutputStream(os);
dis = new DataInputStream(is);
dos = new DataOutputStream(os);
} catch(Exception e){
// ...
}
print(Client Connected);


$ / code>

现在,以前所有的存储都是OOS,对象输出流。所以,你可能会问我为什么要经历创造这些领域的麻烦?答案是我想分离发送自定义对象的原语与发送纯字节。我认为Java在将事情分离出来这样可行。



我注意到的是,突然难以预测的某些对象会导致OutOfMemory Error导致程序崩溃。我知道我可以忘记为IO类使用所有这些不同的装饰器,但我想了解为什么会发生这些内存不足错误?


  • 在多次装饰IO流时是否存在根本性错误?

  • 在实际使用它之前装饰流是否更好,然后让垃圾收集器处理它当它不再需要时?

  • 作为上述问题的扩展,在所有工作都没有内存错误之前,我实际存储的唯一对象是OOS。但是,现在,内存错误与OOS有关。 DOS或OS的创建是否导致垃圾收集器无法正常运行?
  • 包装在两个独立的包装中相同的 InputStream 是不受支持的习惯用法。第一个包装器可能立即读取一些输入来填充其缓冲区;第二个可能会尝试做同样的事情。每个包装都是免费的(甚至是鼓励),可以自行决定是否可以完全读出其基础流。

    因此,简而言之,


    在多次装饰IO流时是否存在根本性错误?

    是的,有。


    This question may seem a little trivial at first, but I am experiencing odd OutOfMemory problems since I began implementing this. After looking through the Java Heap Dumps, I know the memory leak is related to the ObjectOutputStream variable. Without further ado, here is the code:

    In my constructor, I am setting up field variables that will hold my Input/Output Stream variables. Along with it, I am creating two other sets of variables for when I am specifically doing IO on custom objects and then pure primitives:

      public SingleServer(Socket s, int maxThreads) {
        client = s;
        serversCreated.incrementAndGet();
        try {
          is = client.getInputStream();
          os = client.getOutputStream();
          ois = new ObjectInputStream(is);
          oos = new ObjectOutputStream(os);
          dis = new DataInputStream(is);
          dos = new DataOutputStream(os);
        } catch (Exception e) {
          // ...
        }
        print("Client Connected");
    
      }
    

    Now, before, all there was was storage of OOS, the object output stream. So, you may have asking why I am going through the trouble of creating these fields? The answer is I wanted to separate the sending of primitives from the sending of custom objects vs the sending of pure bytes. I thought Java was okay in separating things out like this.

    What I am noticing is that suddenly and hard-to-predictingly some objects now cause OutOfMemory Error's which crash my program. I know I can just forget about using all these different decorators for the IO classes, but I want to understand why these out of memory errors would happen?

    • Is there something fundamentally wrong with decorating your IO stream multiple times?
    • Is it better to decorate a stream on demand, before actually using it, and then let the garbage collector handle it when its no longer needed?
    • As an extension to the above question, before when everything was working without memory errors, the only object I actually stored was OOS. Yet, now, the memory errors are related to OOS. Does the creation of DOS or OS cause the garbage collector to not run properly?

    解决方案

    Wrapping the same InputStream in two independent wrappers is an unsupported idiom. The first wrapper might immediately read some input to fill its buffer; the second one may try to do the same. Each wrapper is free (and even encouraged) to assume that it can fully read out its underlying stream, at its own discretion.

    So, in a nutshell,

    Is there something fundamentally wrong with decorating your IO stream multiple times?

    Yes, there is.

    这篇关于在你的类中使用装饰的OutputStream / InputStream字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆