我自定义了个类class Message implements Serializable { 
Image im; 
Message(Image im){ 
this.im=im; 


也实现了Serializable 接口;但是这个类里面有个Image对象,不能序列化,怎么解决? 问题补充: 
Image off_screen_buf; 
if (off_screen_buf == null) { 
off_screen_buf = this.createImage(1024, 768); 
msg = new Message( off_screen_buf); 
这样做不行的,具体点的! 
out.writeObject(msg);的时候会抛异常: 
java.io.NotSerializableException: sun.awt.image.OffScreenImage  
(我只是想做一个网络绘画板,画板用的双缓冲,所以想直接把off_screen_buf传给其他人,但是在网络上传输的时候遇到了现在这个问题,off_screen_buf不能序列化,应该怎么解决,谢谢!)

解决方案 »

  1.   

    把Image im; 加上关键字transient
    然后自己定义2个方法:
    private void writeObject(ObjectOutputStream stream) throws IOException;
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException;
      

  2.   

    还是不要直接传这个对象,吧Image的数据提出来序列化出去,因为sun.awt.image.OffScreenImage 没有实现序列化接口,不能够序列化
    Image应该有获得byte数组的方法,活动具体数组,用基础数据在网络中传输。
      

  3.   

    有时间看看Java Pitfalls。有两个方法:
    1、是实现扩展序列化接口Externalizable,这样一来就不能使用默认方式序列化,只能在writeExternal()明确序列化那些需要的部分。
       也就是说你需要自己写两个方法: readExternal 和 writeExternal。2、通过transient关键字,transient限定的属性的值将不会被串行化,这些属性会被设置成其类型的java默认值。反串行化并不是重新构造这个对象。
       也就是说实现Serializable接口,不串行化的字段设为transient。
       
       就在Message类中,添加两个方法 readObject 和 writeObject; 对Image进行特殊处理
      

  4.   


    方法一:我肯定都是要序列化的,但问题还是老问题IMAGE不能序列化。
    方法二:对IMAGE怎么特殊处理?具体一点,谢谢!
      

  5.   

        private void writeObject(ObjectOutputStream s) throws IOException {
            ......//其他处理
            
            对Image的处理
            int[] pixels = image != null? new int[w * h] : null;
            if (image != null) {
        try {
            PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
            pg.grabPixels();
            if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
        throw new IOException("failed to load image contents");
            }
        }
        catch (InterruptedException e) {
            throw new IOException("image load interrupted");
        }
            }
            s.writeObject(pixels);
        }
      

  6.   

    对我说的方法一,也是对你的Message实现扩展的序列化接口,并不是Image。因为Serializable的序列化是一个递归的过程,很可能会使得序列化后的对象变得很大....
      

  7.   

    你的方法一和方法二要合并?
    我还是不知道怎么做。transient关键字加上好象就不序列化了,那反序列化的时候也就没有IMAGE对象了。怎么读得到呢?
    实现扩展序列化接口Externalizable
    自己写两个方法: readExternal 和 writeExternal
    在这二个方法里特殊处理IMAGE对象

    是这样吗?
      

  8.   

    实现扩展序列化接口Externalizable这个要完全自己实现序列化。并不是两个方法要合并,这是两个实现。    private void writeObject(ObjectOutputStream s) throws IOException { 
            ......//其他处理 
            
            对Image的处理 
            int[] pixels = image != null? new int[w * h] : null; 
            if (image != null) { 
        try { 
            PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w); 
            pg.grabPixels(); 
            if ((pg.getStatus() & ImageObserver.ABORT) != 0) { 
        throw new IOException("failed to load image contents"); 
            } 
        } 
        catch (InterruptedException e) { 
            throw new IOException("image load interrupted"); 
        } 
            } 
            s.writeObject(pixels); //这不就是Image的处理吗?
        }
      

  9.   


    答:很简单啊.那有那么复杂的事啊.我是在本地抓屏后,将图像通过网络传给对方时写的程序中用的,方法是用:ImageIcon类啊.它可是实现了Serializable 接口的啊.
    即:
    方法如下:我自定义了个类class Message implements Serializable { 
    ImageIcon  im; 
    Message(Image im){ 
    this.im=new ImageIcon(im); 
    } 若要从ImageIcon对象imobj中取出Imaege,则:
    image im=imobj.getImage();就行了.
      

  10.   


    你可以看一下 ImageIcon 的实现,其中的 Image对象就是定义为transient,参考一下它的实现,你就明白了。PS:14楼的使用系统的序列化可能代价是很大的,序列化是递归的。也许要序列化之前东西并不大,但是序列化之后就级数增长了。
      

  11.   

    16楼,说得很对,直接报内存溢出了
    Exception in thread "Thread-1" java.lang.OutOfMemoryError: Java heap space
      

  12.   

    答:ImageIcon并不会比你自己定义的序列化大多少.这你从ImageIcon的源代码就可看到.这个OutOfMemoryError,几乎肯定是线程代码设计上的问题.你每一屏是1024*768,每一个操作(如:画线时,mouse一移动)都是抓一屏传输的吗?贴上你的代码.
      

  13.   

      在鼠标松开的时候发送的 public void mouseReleased(MouseEvent e):
    msg = new Message(off_screen_buf);
    pc.clientPaint.sendmsg(msg);
     下面是clientPaint类里面的方法:
     public void sendmsg(Message msg) {
            try {
                out.writeObject(msg);
            } catch (IOException ex) {
               System.out.print(ex.toString);
            }
            
        }
      

  14.   


    序列话并不是你想的那么简单,一个ImageIcon就是一个int数组......
    它的Observer等其他属性呢,其他属性又会如何实现呢?看看源码,或者有空的话看看 Java Pitfalls 啊,也许你就会理解
      

  15.   

    答:请在out.writeObject(msg); 
    加上:out.flush();否则会:OutOfMemory的!
      

  16.   

    我用ImageIcon类,对象现在是可以传了,但是现在又出现二个问题,一个就是内存溢出。
    另一个就是当我把从网络上接收过来的IMAGE存到自己的画板缓冲即off_screen_buf后,当前用鼠标就不能画了。
     msg = (Message) in.readObject();
     ImageIcon cache = msg.getContent();
     pc.mc.draw(cache.getImage());
    另一类:
        void draw(Image cache) {
             off_screen_buf =cache;
             Graphics g = getGraphics();
            paint(g);
        }
      

  17.   


    加上out.flush();依然会溢出
    画得少不会,画得多的时候就会溢出了。
      

  18.   

    答:即使是你自己实现序列化,每一次都new 一个1024*768的大空间,你几乎一定还是"内存溢出"的. 你的代码中,有没有要能,共用一个或少量几个1024*768的空间,而不是每一个事件,都new一个大的1024*768的空间?
      

  19.   

    不就第一次创建了1024*768的空间的吗,怎么是每一事件New一个呢。后面只是在上面画东西,内容变化而已啊?不对吗?
      

  20.   

    答:是这个: 
    在鼠标松开的时候发送的 public void mouseReleased(MouseEvent e): 
    msg = new Message(off_screen_buf); //<---这个每一次都会内部开一个同样大小的数组,你即使自己对Image序列化(不通过ImageIcon),代码中每一次开一个同样大小的数组,同样内存溢出的.因此:看来最好的办法是:直接针这一个(仅此一个的)off_screen_buf,直接传送它的整个二进制数据
    pc.clientPaint.sendmsg(msg); 
      

  21.   

    JAVA在已有图片上面画图报错UnsupportedOperationException,这个我找到了。要把IMAGE改成BUFFERIMAGE,不知道
    ImageIcon怎么转成BUFFERIMAGE?上一问题:怎么直接传他的二进制呢?
      

  22.   

    最后一问了,问完结贴了:
    ImageIcon怎么转成BufferedImage? 
    或者Image怎么转成BufferedImage?
      

  23.   

    还没结贴呢public static BufferedImage imageToBufferedImage(Image image){    
    Frame frame = null;//创建一个观察者
    try{frame = new Frame();     
        frame.addNotify();     
        MediaTracker mt = new MediaTracker(frame);  
        mt.addImage(image,0);   
        mt.waitForAll();   
        int w = image.getWidth(frame);   
        int h = image.getHeight(frame);   
        BufferedImage buf = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);   
        Graphics gc = buf.createGraphics();   
        gc.drawImage(image,0,0,frame);   
        return   buf;   
    } catch (Exception e){   
        e.printStackTrace();   
        return   null;   
    } finally{
        if(frame != null){
        frame.dispose();
        }
    }
      

  24.   

    BufferedImage转成ImageIcon方法是:ImageIcon imo=new ImageIcon(你的BufferedImage对象);
    反之:BufferedImage bi=(BufferedImage)ImageIcon的对象.getImage();