Results 1 to 18 of 18
  1. #1
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Question How does ObjectOutputStream access private writeObject(ObjectOutputStream) methods?

    Could someone explain to me how does ObjectOutputStream access the user-defined private writeObject(ObjectOutputStream) methods? I would like to use a similar pattern in my code.

    Thanks!

  2. #2
    Ronin is offline Senior Member
    Join Date
    Oct 2010
    Posts
    393
    Rep Power
    5

    Default

    First post and not even a "Hello" :rolleyes:.

    Simple answer is it can't.
    If you want information on how to use Object IO stream, then have a look at the tutorials.

    If you want any assistance after this then post back.

    Regards.

  3. #3
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Ronin View Post
    First post and not even a "Hello" :rolleyes:.
    Sorry... Hello everyone! :P

    Simple answer is it can't.
    Hmm that is inconvenient. I keep hitting walls when I try doing similar stuff as what is done in the JAVA library (I have a C++ background and I am used to have access to the same functionalities as the developers of the standard library).

    If you want information on how to use Object IO stream, then have a look at the tutorials.
    I think that I already have a good idea of how ObjectOutputStream works, but my problem is not directly related to this class in fact. What I am trying to do is to load a bunch of objects from one stream, load another bunch of objects from another stream, then add references to some objects in the first bunch from some of the objects in the second bunch (not all of them). To keep a good encapsulation of my classes I want the function that sets the references to be accessible only from the class that loads the objects from the streams. Since the objects come from two different streams it is not really possible to set the reference (I will refer to it as the setReference function from now) in the constructor. I use the references as a flag to check if objects are linked or not, so I cannot simply "lock" the setReference function once the reference is set. I don't want to use an extra flag either in my classes to lock it down. The objects that implement the setReference functions have to be from a different package and have to be able to extend some arbitrary base class.

    What I would do in C++ is simply using friendship between the class that loads the objects and some base class for all the objects I am serializing and then I would use multiple inheritance for these objects if necessary. Since friendship and multiple inheritance do not exist in Java I can't do that obviously. Interfaces are not helpful either because they only allow public member functions.

    So do you have an idea of how I could achieve what I want in Java without using extra fields?

    Thanks!!
    Last edited by kreyszig; 10-12-2010 at 05:45 PM.

  4. #4
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,762
    Blog Entries
    7
    Rep Power
    21

    Default

    Have a look at the AccessibleObject class; it is part of the reflection framework; in short: using reflection you can access a private method from outside the class where the object is defined. Filthy ...

    kind regards,

    Jos

  5. #5
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    Well, you seem to have decided to do it one way and one way only, by locking out as many other options as possible.

    Not terribly constructive.

    Why not use a flag, for example?
    A boolean is hardly going to break the bank.

  6. #6
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Have a look at the AccessibleObject class; it is part of the reflection framework; in short: using reflection you can access a private method from outside the class where the object is defined. Filthy ...

    kind regards,

    Jos
    Interesting. I will read more about it. Will such a solution always work, I mean, is it something that is disabled on some JVMs? This is a bit weird to have to break class encapsulation to then ensure it, but if it is the only solution...

  7. #7
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    As Jos says, though...it's not really a good idea.
    If you find yourself doing this then you're probably doing something wrong.

  8. #8
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    Well, you seem to have decided to do it one way and one way only, by locking out as many other options as possible.

    Not terribly constructive.

    Why not use a flag, for example?
    A boolean is hardly going to break the bank.
    I am opened to solutions, it is just that I will be generating many millions of these objects, so I want to avoid adding extra fields to ensure encapsulation. It would be neat if I could simply use a static flag... Maybe I could use some kind of locking mechanism in the class that load the objects (using static functions and fields) and then check the status of the lock from the setReference function of the objects?
    Last edited by kreyszig; 10-12-2010 at 06:48 PM.

  9. #9
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,762
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by kreyszig View Post
    Interesting. I will read more about it. Will such a solution always work, I mean, is it something that is disabled on some JVMs? This is a bit weird to have to break class encapsulation to then ensure it, but if it is the only solution...
    Well, reflection (or 'introspection') is filthy to start with but serialization must use it (as you have already noticed). If a user program has to use it it's time to rethink your design. Reflection is the gateway to just C (or C++) programming; so far for type safety and visibilty.

    kind regards,

    Jos

  10. #10
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    Quote Originally Posted by kreyszig View Post
    I am opened to solutions, it is just that I will be generating many millions of these objects, so I want to avoid adding extra fields to ensure encapsulation. It would be neat if I could simply use a static flag... Maybe I could use some kind of locking mechanism in the class that load the objects (using static functions and fields) and then check the status of the lock from the setReference function of the objects?
    Well then, do you need to hold all these objects in memory at once?

    I'm still not entirely clear what it is you are trying to achieve?

    Are you trying to stop someone writing code to setReference()?

  11. #11
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    Well then, do you need to hold all these objects in memory at once?
    Yes unfortunately, otherwise I will be reading and writing them constantly which will make my code inefficient to run...

    Quote Originally Posted by Tolls View Post
    I'm still not entirely clear what it is you are trying to achieve?

    Are you trying to stop someone writing code to setReference()?
    yes this is what I am trying to do. I think I might have a solution though. Suppose my class that loads the objects is called ObjectLoader, I go do something like the following in the setReference function:

    final public void setReference(Object obj) {
    if(ObjectLoader.isUnlocked()) reference=obj;
    else throw ...
    }

    So I could use a static lock in ObjectLoader and lock it right after setting the references for all the objects I load. The problem though is that it would encapsulate the mechanism for the users of the classes that I am serializing (or more correctly of the classes for which I am serializing instances), but it would not encalulate the mechanism from inside the serialized classes themselves. As I mentioned these classes will not be part as the same package as ObjectLoader. So this would rely on the implementation of the serialized classes to ensure the encapsulation. These classes would need to implement setReference as final and would have to make sure that the reference field is private and cannot be modified by users. To implement setReference in a base class would fix it, but as I said this would prevent the serialized classes from inheriting from another base class. Any more idea?
    Last edited by kreyszig; 10-12-2010 at 07:29 PM.

  12. #12
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    If you want to make it noticeable (in any IDE) simply mark the method as deprecated, with a note.

    I just think you're overthinking this.

  13. #13
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    Right, a nights kip and let's look at this from another angle.

    Here's my proposal.
    I'm treating the objects you're working on as implementing an interface that contains setReference(), as follows. Up to you whether you actually use it as an interface, but it makes it easier for me to describe (apologies for rubbish names!).
    Java Code:
    public interface Referenceable {
        void setReference(ReferenceHolder holder);
    }
    Now, the ReferenceHolder is part of your processing class. Not knowing your design you'll have to figure out how to handle this bit:
    Java Code:
    public class ObjectProcessor {
    
        public class ReferenceHolder {
            private Object reference;
            private ReferenceHolder(Object reference) {
                this.reference = reference;
            }
            public Object getReference() {
                return reference;
            }
        }
    
        private void handleReference(Referenceable r, Object reference) {
            r.setReference(new ReferenceHolder(reference));
        }
    }
    Now, only ObjectProcessor can create ReferenceHolders, so no one can use setReference() (except to set it to null, which you can check for in the method).

    ETA: Oh, and the concrete code for setReference will be:
    Java Code:
    this.reference = holder.getReference();
    Last edited by Tolls; 10-13-2010 at 10:06 AM. Reason: Missed a public.

  14. #14
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    Right, a nights kip and let's look at this from another angle.

    Here's my proposal.
    I'm treating the objects you're working on as implementing an interface that contains setReference(), as follows. Up to you whether you actually use it as an interface, but it makes it easier for me to describe (apologies for rubbish names!).
    Java Code:
    public interface Referenceable {
        void setReference(ReferenceHolder holder);
    }
    Now, the ReferenceHolder is part of your processing class. Not knowing your design you'll have to figure out how to handle this bit:
    Java Code:
    public class ObjectProcessor {
    
        public class ReferenceHolder {
            private Object reference;
            private ReferenceHolder(Object reference) {
                this.reference = reference;
            }
            public Object getReference() {
                return reference;
            }
        }
    
        private void handleReference(Referenceable r, Object reference) {
            r.setReference(new ReferenceHolder(reference));
        }
    }
    Now, only ObjectProcessor can create ReferenceHolders, so no one can use setReference() (except to set it to null, which you can check for in the method).

    ETA: Oh, and the concrete code for setReference will be:
    Java Code:
    this.reference = holder.getReference();
    Yes, this would do it! It requires an extra reference for each instance of the classes implementing Referenceable though. Is it safe to assume that references use 4 bytes on 32 bit machines and 8 bytes on 64 bit machines in Java?

  15. #15
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    Sorry, I assumed you were holding these references anyway on the objects.

    The ReferenceHolder will be eligible for gc as soon as handleReference() ends.

  16. #16
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    Sorry, I assumed you were holding these references anyway on the objects.

    The ReferenceHolder will be eligible for gc as soon as handleReference() ends.
    Right now I am holding references to other Referenceable objects directly in my Referenceable instances. So with that new solution I would be holding a reference to ReferenceHolder which would then hold a reference to Referenceable. The issue is that I think I will have to keep the ReferenceHolder instances alive as long as the Referenceable instances exist because I will be using these references until I destroy the Referenceable instances...

  17. #17
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,225
    Rep Power
    20

    Default

    No you wouldn't.
    The sole purpose of the holder is to pass the actual reference into the object.
    So the implementation of setReference on your Referenceable (I'm sure there's a better name for that..:)) would look like:
    Java Code:
    public void setReference(ReferenceHolder holder) {
        this.reference = holder.getReference();
    }
    This is as secure as anything you'd get from the C++ equivalent, from what I can see.

  18. #18
    kreyszig is offline Member
    Join Date
    Oct 2010
    Posts
    35
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    No you wouldn't.
    The sole purpose of the holder is to pass the actual reference into the object.
    So the implementation of setReference on your Referenceable (I'm sure there's a better name for that..:)) would look like:
    Java Code:
    public void setReference(ReferenceHolder holder) {
        this.reference = holder.getReference();
    }
    This is as secure as anything you'd get from the C++ equivalent, from what I can see.
    Doh! Yes sorry you are absolutely right. This is a very elegant solution. Thanks!

Similar Threads

  1. has private access error message
    By ibrahimyoussof in forum Enterprise JavaBeans (EJB)
    Replies: 2
    Last Post: 04-13-2010, 05:01 PM
  2. problem using ObjectOutputStream in multithreading
    By sanjeevbindroo in forum Networking
    Replies: 3
    Last Post: 10-15-2009, 09:00 AM
  3. How to access private data types from public classes?
    By kevzspeare in forum New To Java
    Replies: 3
    Last Post: 03-07-2009, 05:19 AM
  4. ObjectOutputStream Example
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 03-20-2008, 10:21 AM
  5. question on ObjectOutputStream
    By money123 in forum New To Java
    Replies: 5
    Last Post: 07-27-2007, 11:31 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •