This discussion is archived
1 2 Previous Next 15 Replies Latest reply: Mar 11, 2010 4:54 AM by 843798 RSS

How to get the values of the objects inside an object??

795628 Newbie
Currently Being Moderated
Hi,
I am trying to write code to display name and memory usage of all session attributes, in a recursive way.

I suppose reflection is needed here, but I can’t figure out how to get the values of the objects inside an object...
private void handleIt(String attributeName, Object attributeValue) {
     boolean isPrimitiveOrNull = ((null == attributeValue) || 
          (attributeValue.getClass().isPrimitive()));                                         
     if (isPrimitiveOrNull) {
          sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "}");
     } else {
          sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "{");               
          Field[] fields = attributeValue.getClass().getDeclaredFields();
          int lim = fields.length;
          String name;
          Object value = null;
          for (int i = 0; i < lim; i++) {
               name = fields.getName();
                    
               //LOOK AT THIS LINE: !!!!!!!!!!!!!!!!!!!!!!!!!!!
               value = fields[i].get(obj); //I don´t know what 'obj' should be??
                    
               handleIt(name, value);
          }               
          sb.append("}");               
     }          
}



Any suggestions will be greatly appreciated...
  • 1. Re: How to get the values of the objects inside an object??
    843798 Newbie
    Currently Being Moderated
    Well, what does the JavaDoc say about that parameter?

    What information do you think is still missing from that call?
    JLuis wrote:
    I am trying to write code to display name and memory usage of all session attributes, in a recursive way.
    Btw: how did you implement sizeOf()? That method can almost certainly implement just a crude guess (unless you use some JVM-specific mechanism).
  • 2. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    I get it:
    value = fields.get(attributeValue);


    Here sizeOf method, which use the strategy of copy the object to a byte stream and calculate its length:
         private int sizeOf(Object obj) {
              //Valid only for Serializables
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              ObjectOutputStream oos = null;     
              byte[] bytes = null;
                   
              try {          
                   oos = new ObjectOutputStream(baos);
                   oos.writeObject(obj);
                   bytes = baos.toByteArray();
              } catch(Exception e) {               
                   //PENDIENTE: Tratamiento excepción
              } finally {
                   if (oos != null) {
                        try {
                             oos.close();
                        } catch(Exception e) {
                             //PENDIENTE: Tratamiento excepción                         
                        }
                   }
                   if (baos != null) {
                        try {
                             baos.close();
                        } catch(Exception e) {
                             //PENDIENTE: Tratamiento excepción                         
                        }
                   }               
              }
              
              int size = -1;
              if (bytes != null) {
                   size = bytes.length;
              }
              return size;          
         }
    Now I am fighting with StackOverflows
  • 3. Re: How to get the values of the objects inside an object??
    843798 Newbie
    Currently Being Moderated
    JLuis wrote:
    Now I am fighting with StackOverflows
    Probably because you get an object o1 that references o2, which in turn references o1. If that's the case and you do the simple (naive) traversal of the object graph, then you pretty quickly land in an infinite loop.
  • 4. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    Thanks Joachim,
    any ideas on how to avoid that cyclic references?
  • 5. Re: How to get the values of the objects inside an object??
    843798 Newbie
    Currently Being Moderated
    JLuis wrote:
    Thanks Joachim,
    any ideas on how to avoid that cyclic references?
    A common way is to hold a Set of all object you visited and simply skip any object that you already have in the Set.

    Out of curiosity: is that something you plan to do very often (for example: each request) or just occasionally? And what do you plan to do with the data?

    Because the process sounds rather expensive (both in terms of CPU and memory) and the numbers you get are just a very crude approximation of the actual memory consumption.
  • 6. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    Hi again,
    I follow the 'set' advice. But contains() method is not working as I expected:
    Any hints??
    ...
    private Set<String> objects = Collections.synchronizedSet(new HashSet<String>());
    ...
    private void handleIt(String attributeName, Object attributeValue) {
         boolean isPrimitiveOrNull = ((null == attributeValue) || (attributeValue.getClass().isPrimitive()));                                         
         if (isPrimitiveOrNull) {
              sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "}");
         } else {
              sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "{");               
              Field[] fields = attributeValue.getClass().getDeclaredFields();
              String name;
              Object value = null;
              int lim = fields.length;
              for (int i = 0; i < lim; i++) {
                   name = fields.getName();                    
                   if (!objects.contains(name)) {
                        //Always enters here ¿¿¿¿¿¿¿¿¿¿¿¿¿???????????               
                        try {
                             value = fields[i].get(attributeValue);
                        } catch(Exception e) {
                             //PENDIENTE: Tratamiento excepción
                        }                              
                        handleIt(name, value);                    
                        objects.add(name);
                   }
              }
              sb.append("}");               
         }          
    }



    (Answering your question: yes, I just want to run this code occasionally...)

    Thanks for your replys..
  • 7. Re: How to get the values of the objects inside an object??
    843798 Newbie
    Currently Being Moderated
    You can replace the .contains() call with a call to .add(), because add will return a boolean indicating if the Set changed as a reaction to the add (i.e. it will return true, if the Set did not contain the object before).

    In your case you want to ignore the equals() and hashCode() implementation of all objects, so you might want to use an IdentityHashSet.
  • 8. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    Hi,
    Do you mean 'IdentityHashMap'??
  • 9. Re: How to get the values of the objects inside an object??
    843798 Newbie
    Currently Being Moderated
    JLuis wrote:
    Do you mean 'IdentityHashMap'??
    Yes, I always forget that there is no IdentityHashSet.

    You can use Collections.newSetFromMap() and a IdentityHashMap to get what would be called an IdentityHashSet ;-)
  • 10. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    I realized that massive int objects called MAX_VALUE, MIN_VALUE and SIZE where causing the StackOverflow, so I removed them from the analysis.

    This is the resultant code. But I think it isn’t accurate in calculating the real size of objects being got using reflexion.

    Do you or somebody have any more suggestions?
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Field;
    import java.util.Enumeration;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class SessionMeasurer extends HttpServlet {
    
         private static final long serialVersionUID = 1470488362727841992L;
         private StringBuilder sb = new StringBuilder();
         
         public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              performTask(request, response);
         }
    
         public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              performTask(request, response);
         }
    
         public void performTask(HttpServletRequest request, HttpServletResponse response) {
              HttpSession     session = request.getSession(false);     
              String attributeName = "";
              Object attributeValue = null;
              for (Enumeration<?> attributeNames = session.getAttributeNames(); attributeNames.hasMoreElements();) {
                   attributeName = (String)attributeNames.nextElement();
                   attributeValue = session.getAttribute(attributeName);
                   handleIt(attributeName, attributeValue);               
              }          
              System.out.println(sb.toString());
         }
    
         private void handleIt(String attributeName, Object attributeValue) {           
              if (attributeValue != null) {          
                   boolean isPrimitive = attributeValue.getClass().isPrimitive();
                   if (isPrimitive) {
                        sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "}");
                   } else {
                        sb.append("{" + attributeName + ":" + sizeOf(attributeValue) + "{");               
                        Field[] fields = attributeValue.getClass().getDeclaredFields();
                        String name;
                        Object value = null;
                        int lim = fields.length;
                        for (int i = 0; i < lim; i++) {
                             name = fields.getName();                                                                                                         
                             if (!name.endsWith("_VALUE") && !name.equals("SIZE") && !name.equals("serialVersionUID")) {
                                  try {
                                       value = fields[i].get(attributeValue);
                                  } catch(Exception e) {
                                       //PENDIENTE: Tratamiento excepción
                                  }          
                                  handleIt(name, value);
                             }
                        }
                        sb.append("}");               
                   }          
              }
         }
         
         private int sizeOf(Object obj) {
              //Valid only for Serializables
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              ObjectOutputStream oos = null;     
              byte[] bytes = null;               
              try {          
                   oos = new ObjectOutputStream(baos);
                   oos.writeObject(obj);
                   bytes = baos.toByteArray();
              } catch(Exception e) {               
                   //PENDIENTE: Tratamiento excepción
              } finally {
                   if (oos != null) {
                        try {
                             oos.close();
                        } catch(Exception e) {
                             //PENDIENTE: Tratamiento excepción                         
                        }
                   }
                   if (baos != null) {
                        try {
                             baos.close();
                        } catch(Exception e) {
                             //PENDIENTE: Tratamiento excepción                         
                        }
                   }               
              }          
              int size = -1;
              if (bytes != null) {
                   size = bytes.length;
              }
              return size;          
         }
                   
    }
  • 11. Re: How to get the values of the objects inside an object??
    jtahlborn Expert
    Currently Being Moderated
    you should ignore static fields.
  • 13. Re: How to get the values of the objects inside an object??
    EJP Guru
    Currently Being Moderated
    Because they aren't part of the object, they are part of the class.
  • 14. Re: How to get the values of the objects inside an object??
    795628 Newbie
    Currently Being Moderated
    And, how can I know if one is static?

    I see fields.getModifiers() returns and int; but what is the int-code for 'statics'?

    thanks!
1 2 Previous Next