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

Posted

篇首语:活着,如同生命中最后一天般活着。学习,如同你会永远活着般学习。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java中类似于C语言中Sizeof功能实现(二)相关的知识,希望对你有一定的参考价值。

Java中类似于C语言中Sizeof功能实现(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  在做了所有这些准备之后 下面就是这种图形遍历的标准实现   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 ponentType = objClass getComponentType ();    // Add shell pseudo node:  final AbstractShellProfileNode shell =  new ArrayShellProfileNode (node objClass arrayLength);  shell m_size = sizeofArrayShell (arrayLength ponentType);    node m_shell = shell;  node addFieldRef (shell);    if (! ponentType isPrimitive ())    // Traverse each array slot:  for (int i = ; 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."使用的"通过反射克隆"实现的远亲。wingwIt.如前所述,它缓存了反射元数据来提高性能,并且使用了一个标识散列映射来标记访问过的对象。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);    ...     // End of interface    节点访问者只有当伴随的过滤器为null或者过滤器接收该节点时才对树节点进行操作。为了简便,节点的子节点只有当节点本身已经测试时才进行测试。前序遍历和后序遍历访问都支持。来自java.lang.Object处理程序的尺寸提供以及所有初级数据都集中放在一个伪码内,这个伪码附属于代表对象实例的每个"真实"节点。这种处理程序节点可通过IObjectProfileNode.shell()访问,也可在IObjectProfileNode.children()列表中显示出来:目的就是能够编写数据过滤器和访问者,使它们可在实例化的数据类型的同一起点上考虑初级数据。  如何实现过滤器和访问者就是你的事了。作为一个起点,类ObjectProfileFilters (见本文的download)提供几种有用的堆栈过滤器,它们可帮助你在节点尺寸、与父节点的尺寸相关的节点尺寸、与根对象相关的节点尺寸等等的基础上剪除大对象树。  ObjectProfilerVisitors类包含IObjectProfileNode.dump()使用的默认访问者,也包含能够为更高级的对象浏览创建XML转储的访问者。将配置文件转换为SwingTreeModel也是很容易的。  为了便于理解,我们创建了一个上文提及的两个字符串排列对象的完整转储:    public class Main    public static void main (String [] args)    Object obj = new String [] new String ("JavaWorld"),  new String ("JavaWorld");    IObjectProfileNode profile = ObjectProfiler.profile (obj);    System.out.println ("obj size = " + profile.size () + " bytes");  System.out.println (profile.dump ());       // End of class     该代码结果如下:  obj size = 106 bytes  106 -> : String[]  58 (54.7%) -> [0] : String  34 (32.1%) -> String#value : char[] refcount=    ( %) > length= >   ( %) > prim/ ref fields>   ( %) > length= >   ( %) > [ ] : String   ( %) > prim/ ref fields>    实际上 如前所述 内部的字符排列(被java lang String#value访问) 可被两个字符串共享 即使ObjectProfiler profile()将该排列的从属关系指向第一个发现的字符串 它还是通知说 该排列共享(如它的下一句代码refcount= 所示)     简单的sizeof()  ObjectProfiler profile()创建了一个节点图形 它的尺寸一般来说是原始对象图形的几倍 如果你只需要根对象尺寸 你可以使用更快更有效的方法ObjectProfile cha138/Article/program/Java/JSP/201311/19338

相关参考

知识大全 java中super的两种用法

  通过用static来定义方法或成员为我们编程提供了某种便利从某种程度上可以说它类似于C语言中的全局函数和全局变量  但是并不是说有了这种便利你便可以随处使用如果那样的话你便需要认真考虑一下自己是否

知识大全 Java语言中Timer类的简洁用法(二)

Java语言中Timer类的简洁用法(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  实现计

知识大全 计算机二级中C语言、VB、VF、JAVA、Access、C++,有什么不同

计算机二级中C语言、VB、VF、JAVA、Access、C++,有什么不同?考哪一类别比较好?  以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理

知识大全 java语言与c++相比,有哪些优点?

java语言与c++相比,有哪些优点?主要是这两种开发者对内存地址变量的不同理解,使两种语言在编程的思维上有所差异。C中存在指针变量,而且每个指针对应着一个真实的物理内存地址,他可以对相应地址中的内存

知识大全 Java语言中字符的处理

Java语言中字符的处理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  摘要本文主要讨论了Jav

知识大全 Java 编程语言中的口令屏蔽

Java编程语言中的口令屏蔽  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  目前对于Java命令

知识大全 JAVA语言编程中如何使用表达式

JAVA语言编程中如何使用表达式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JAVA正则表达

知识大全 分享关于Java 语言中的函数编程

分享关于Java语言中的函数编程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  如果您从事大型企

知识大全 Java语言中Timer类的简洁用法(一)

Java语言中Timer类的简洁用法(一)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  所有类

知识大全 Java编程语言中的return语句介绍

Java编程语言中的return语句介绍  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!lishix