Java中类似于C语言中Sizeof功能实现(二)

王朝java/jsp·作者佚名  2008-05-31
宽屏版  字体: |||超大  

在做了所有这些预备之后,下面就是这种图形遍历的标准实现:

public static IObjectProfileNode profile (Object obj)

{

final IdentityHashMap visited = new IdentityHashMap ();

final ObjectProfileNode root = createProfileTree (obj, visited,

CLASS_METADATA_CACHE);

finishProfileTree (root);

return root;

}

private static ObjectProfileNode createProfileTree (Object obj,

IdentityHashMap visited,

Map metadataMap)

{

final ObjectProfileNode root = new ObjectProfileNode (null, obj, null);

final LinkedList queue = new LinkedList ();

queue.addFirst (root);

visited.put (obj, root);

final ClassAccessPrivilegedAction caAction =

new ClassAccessPrivilegedAction ();

final FieldAccessPrivilegedAction faAction =

new FieldAccessPrivilegedAction ();

while (! queue.isEmpty ())

{

final ObjectProfileNode node = (ObjectProfileNode) queue.removeFirst ();

obj = node.m_obj;

final Class objClass = obj.getClass ();

if (objClass.isArray ())

{

final int arrayLength = Array.getLength (obj);

final Class componentType = objClass.getComponentType ();

// Add shell pseudo-node:

final AbstractShellProfileNode shell =

new ArrayShellProfileNode (node, objClass, arrayLength);

shell.m_size = sizeofArrayShell (arrayLength, componentType);

node.m_shell = shell;

node.addFieldRef (shell);

if (! componentType.isPrimitive ())

{

// Traverse each array slot:

for (int i = 0; i {final Object ref = Array.get (obj, i);if (ref != null){ObjectProfileNode child =(ObjectProfileNode) visited.get (ref);if (child != null)++ child.m_refcount;else{child = new ObjectProfileNode (node, ref,new ArrayIndexLink (node.m_link, i));node.addFieldRef (child);queue.addLast (child);visited.put (ref, child);}}}}}else // the object is of a non-array type{final ClassMetadata metadata =getClassMetadata (objClass, metadataMap, caAction, faAction);final Field [] fields = metadata.m_refFields;// Add shell pseudo-node:final AbstractShellProfileNode shell =new ObjectShellProfileNode (node,metadata.m_primitiveFieldCount,metadata.m_refFields.length);shell.m_size = metadata.m_shellSize;node.m_shell = shell;node.addFieldRef (shell);// Traverse all non-null ref fields:for (int f = 0, fLimit = fields.length; f{final Field field = fields [f];final Object ref;try // to get the field value:{ref = field.get (obj);}catch (Exception e){throw new RuntimeException ("cannot get field [" +field.getName () + "] of class [" +field.getDeclaringClass ().getName () +"]: " + e.toString ());}if (ref != null){ObjectProfileNode child =(ObjectProfileNode) visited.get (ref);if (child != null)++ child.m_refcount;else{child = new ObjectProfileNode (node, ref,new ClassFieldLink (field));node.addFieldRef (child);queue.addLast (child);visited.put (ref, child);}}}}}return root;}private static void finishProfileTree (ObjectProfileNode node){final LinkedList queue = new LinkedList ();IObjectProfileNode lastFinished = null;while (node != null){// Note that an unfinished nonshell node has its child count// in m_size and m_children[0] is its shell node:if ((node.m_size == 1) (lastFinished == node.m_children [1])){node.finish ();lastFinished = node;}else{queue.addFirst (node);for (int i = 1; i{final IObjectProfileNode child = node.m_children [i];queue.addFirst (child);}}if (queue.isEmpty ())return;elsenode = (ObjectProfileNode) queue.removeFirst ();}}该代码是上一篇Java Q&A, "Attack of the Clones."使用的"通过反射克隆"实现的远亲。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有