当前位置:编程学习 > JSP >>

Java中的Sizeof(二)

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

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 < arrayLength; ++ 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 < fLimit; ++ 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 < node.m_size; ++ i)
{
final IObjectProfileNode child = node.m_children [i];
queue.addFirst (child);
}
}

if (queue.isEmpty ())
return;
else
node = (ObjectProfileNode) queue.removeFirst ();
}
}



该代码是上一篇Java Q&A, "Attack of the Clones."使用的"通过反射克隆"实现的远亲。如前所述,它缓存了反射元数据来提高性能,并且使用了一个标识散列映射来标记访问过的对象。 profile()方法从宽度优先遍历中的具有IObjectProfileNode的生成树的原始对象图形开始,以合计和分配所有节点尺寸的快速后序遍历结束。profile()返回一个 IObjectProfileNode,即产生的生成树的根,它的尺寸就是整个图形的尺寸。
当然, profile()的输出只有当我有一个很好的方法扩展它时才有用。为了这个目的,每个IObjectProfileNode 必须支持由节点访问者和节点过滤器一起进行的测试:


interface IObjectProfileNode
{
interface INodeFilter
{
boolean accept (IObjectProfileNode node);

} // End of nested interface

interface INodeVisitor
{
/**
* Pre-order visit.
*/
void previsit (IObjectProfileNode node);

/**
* Post-order visit.
*/
void postvisit (IObjectProfileNode node);

} // End of nested interface

boolean traverse (INodeFilter filter, INodeVisitor visitor);

上一个:Java实现分类文件拷贝
下一个:Java软件开发学习笔记(二)

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,