Staffan, On Jan 9, 2015, at 7:38 AM, Staffan Larsen wrote:
> It’s getting difficult to get all the information into the same output: > hierarchy, interfaces, class loaders and modules. I took a stab at it and it > could look like this: > > java.lang.Object > |--java.io.Serializable (java.base, 0x00000007c00375f8, iface) > |--java.util.RandomAccess (java.base, 0x00000007c00375f8, iface) > |--java.lang.Iterable (java.base, 0x00000007c00375f8, iface) > | |--java.util.Collection (java.base, 0x00000007c00375f8, iface) > | | |--java.util.List (java.base, 0x00000007c00375f8, iface) > |--java.util.AbstractCollection (java.base, 0x00000007c00375f8) > | | implements java.util.Collection > | | implements java.lang.Iterable > | |--java.util.AbstractList (java.base, 0x00000007c00375f8) > | | implements java.util.List > | | |--java.util.Arrays$ArrayList (java.base, 0x00000007c00375f8) > | | | implements java.io.Serializable > | | | implements java.util.RandomAccess > > > But this is pushing what can be visualized in one place. > > We will need to add module and class loader information somehow to all the > Diagnostic Commands that list classes. In addition we will need a way to see > how modules relate to one another. Perhaps it isn’t possible to have all the > information in one place, but instead make it possible to cross reference > between different diagnostic commands. For example, GC.class_stats could have > the module and class loader information, and GC.class_hierarchy would not > have to include it. What is missing from making that possible is a unique way > of identifying a class (since the name is not unique). All output would need > to include that unique identifier and it would be possible to cross > reference. The identifier has to be stable during a JVM run, but not between > runs. I like where you are going with this. Since a given module is within a class loader, putting the the loader/module/class information in class_stats would be helpful and then having other dcmds just need the class/class loader pair for uniqueness. Not sure what you are using below for unique identifier. I would be tempted to use the class loader hex value since otherwise you are introducing hex values that have no meaning other than as cross-references. And the class/class loader pair is guaranteed uniqueness. For any class loader you could list its hex value thereby giving the information in a single command that gives meaning to the loader value. java.lang.Object/null ... |-sun.misc.Launcher$AppClassLoader/null (0xyyy) |-myapp/0xyyy Just a thought. If you are not enthused - I am ok with your proposal. thanks, Karen > > The above would then become: > > java.lang.Object/0x12345600 > |--java.io.Serializable/0x12345601 > |--java.util.RandomAccess/0x12345602 > |--java.lang.Iterable/0x12345603 > | |--java.util.Collection/0x12345604 > | | |--java.util.List/0x12345605 > |--java.util.AbstractCollection/0x12345606 > | | implements java.util.Collection/0x12345604 > | | implements java.lang.Iterable/0x12345603 > | |--java.util.AbstractList/0x12345607 > | | implements java.util.List/0x12345605 > | | |--java.util.Arrays$ArrayList/0x12345608 > | | | implements java.io.Serializable/0x12345601 > | | | implements java.util.RandomAccess/0x12345602 > > With additions to GC.class_stats: > > Index Super ClassLoader ClassName > 1 -1 0x00000007c0034c48 java.lang.Object/0x12345600 > 2 1 0x00000007c0034c48 java.util.List/0x12345605 > 3 31 0x00000007c0034c48 java.util.AbstractList/0x12345607 > > And GC.class_histogram: > > num #instances #bytes class name > ---------------------------------------------- > 1: 945 117736 java.lang.Object/0x12345600 > 2: 442 50352 java.util.List/0x12345605 > 3: 499 25288 java.util.AbstractList/0x12345607 > > > > /Staffan > >> On 9 jan 2015, at 09:53, Frederic Parain <frederic.par...@oracle.com> wrote: >> >> >> >> On 01/08/2015 10:29 PM, Chris Plummer wrote: >>> Hi Karen, >>> >>> Comments inline. >>> >>> On 1/8/15 8:07 AM, Karen Kinnear wrote: >>>> Chris, >>>> >>>> Thank you for doing this. I had a couple of questions/comments. >>>> >>>> I like your idea of being able to start with a specific class to show >>>> all subclasses of. >>> Ok. I'll add that. >>>> >>>> I think the way I read the code this shows the superclass hierarchy, >>>> not the superinterfaces. With the addition >>>> of default methods in interfaces, I think we have increased the value >>>> in seeing superinterfaces. >>> It does include interfaces in the output, but not as part of any class >>> hierarchy. Interfaces are just shown as regular classes that inherit >>> from Object. This is the case if one interface extends another, I >>> suppose because "extends" is just interpreted as "implements" in this case. >>>> >>>> So what I personally would find useful would be to be able to start >>>> with a specific class and >>>> find the superclasses and superinterfaces of that class - for the >>>> debugging I do, I usually am >>>> trying to look up and need both sets of information. Today if you run >>>> -XX:+TraceDefaultMethods >>>> there is one sample way to display all the supertypes of a single >>>> type, all the way up. I don't know the >>>> best way to make that consistent with the current output approach, >>>> e.g. using the |- syntax. >>>> >>>> e.g. >>>> Class java.util.Arrays$ArrayList requires default method processing >>>> java/util/Arrays$ArrayList >>>> java/util/AbstractList >>>> java/util/AbstractCollection >>>> java/lang/Object >>>> java/util/Collection >>>> java/lang/Object >>>> java/lang/Iterable >>>> java/lang/Object >>>> java/util/List >>>> java/lang/Object >>>> java/util/Collection >>>> java/lang/Object >>>> java/lang/Iterable >>>> java/lang/Object >>>> java/util/RandomAccess >>>> java/lang/Object >>>> java/io/Serializable >>>> java/lang/Object >>>> >>>> Do you think there could be value to others in the ability to walk up >>>> the hierarchy as well as to >>>> see superclasses and superinterfaces at least from that perspective? >>> This is a inverted from how my dcmd prints the hierarchy, plus also >>> includes interfaces. Inverting the hierarchy means a class is listed >>> with every subclass of the class, which I don't think is desirable. >>> Including interfaces has the same issue, but introduces a new issue even >>> when not inverting the hierarchy. The same interface can be in more than >>> one location in the hierarchy, so there is no avoiding printing it more >>> than once, so we need to decide how to best include interfaces in the >>> output. >> >> It seems to me that we have two very different use cases here, each one >> best served with a different output format: >> >> 1 - Listing of all classes/interfaces hierarchy when the dcmd is >> invoked without arguments: >> -> Chris' output format as described below (with interfaces) >> 2 - Investigation on a particular class or interface when a class >> or interface is passed in argument to the dcmd >> -> Karen's output format, much easier to work with to >> track default methods. Because the output is limited to the >> hierarchy from a single class, there's no class duplication >> in output (single parent class inheritance) and limited >> interfaces duplication. >> >> If the implementations of the two features are too different, we could >> consider having two different dcmds. >> >> My 2 cents, >> >> Fred >> >>> The could just be a simple list right after the class that >>> implements them: >>> >>> java.lang.Object >>> | ... >>> |--MyBaseClass >>> | | implements -> MyInterface1 >>> | | implements -> MyInterface2 >>> | |--MySubClass >>> | implements -> MyInterface1 >>> | implements -> MyInterface2 >>> | ... >>> |--MyInterface1 >>> |--MyInterface2 >>> >>> The "implements" lines could be optional. >>> >>> I know cvm would distinguish between interfaces the Class declared it >>> implemented, and those it inherited from the interfaces it declared it >>> implemented. This was necessary for reflection, and I think also to >>> properly build up interfaces tables. I assume hotspot does something >>> similar. Is there any need for this information to be conveyed in the >>> above output, or just list out every interface implemented, and not >>> worry about how the class acquired it. >>>> Is there value in printing the defining class loader for each class - >>>> maybe optionally? >>> This is already available with GC.class_stats, although not in the >>> default output. I suppose the reality is that it might be better handled >>> by this DCMD. The main puprose of GC.class_stats is to print statistics >>> (counts and sizes), so printing the ClassLoader name there is probably >>> not appropriate, but then it's not really appropriate for >>> VM.class_hierarchy either. I'm not sure how best to handle this. One or >>> both DCMDs possibly should be re-purposed and more clearly define what >>> type of data it displays. >>>> If so, I'm wondering if there might be value in future for the jigsaw >>>> project adding the module for each class - maybe optionally as well? >>> This relates to my above statement. We need to figure out what type of >>> data is useful, and which dcmds should handle them. >>>> Love opinions on that - especially from the serviceability folks >>>> >>>> thanks, >>>> Karen >>> Thanks for the input. >>> >>> Chris >>>> >>>> >>>> On Jan 7, 2015, at 6:29 PM, Chris Plummer wrote: >>>> >>>>> Hi, >>>>> >>>>> Please review the following changes for the addition of the >>>>> VM.class_hierarchy DCMD. Please read the bug first for some >>>>> background information. >>>>> >>>>> Webrev: http://cr.openjdk.java.net/~cjplummer/8054888/webrev.00/ >>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8054888 >>>>> >>>>> I expect there will be further restructuring or additional feature >>>>> work. More discussion on that below. I'm not sure if that additional >>>>> work will be done later with a separately bug filed or with this >>>>> initial commit. That's one thing I want to work out with this review. >>>>> >>>>> Currently the bulk of the DCMD is implemented in heapInspection.cpp. >>>>> The main purpose of this file is to implement the GC.class_stats and >>>>> GC.class_histogram DCMDs. Both of them require walking the java heap >>>>> to count live objects of each type, thus the name >>>>> "heapInspection.cpp". This new VM.class_hierarchy DCMD does not >>>>> require walking the heap, but is implemented in this file because it >>>>> leverages the existing KlassInfoTable and related classes >>>>> (KlassInfoEntry, KlassInfoBucket, and KlassClosure). >>>>> >>>>> KlassInfoTable makes it easy to build a database of all loaded >>>>> classes, save additional info gathered for each class, iterate over >>>>> them quickly, and also do quick lookups. This exactly what I needed >>>>> for this DCMD, thus the reuse. There is some downside to this. For >>>>> starters, heapInspection.cpp is not the proper place for a DCMD that >>>>> has nothing to do with heap inspection. Also, KlassInfoEntry is being >>>>> overloaded now to support 3 different DCMDs, as is KlassInfoTable. As >>>>> a result each has a few fields and methods that are not used for all >>>>> 3 DCMDs. Some subclassing might be in order here, but I'm not sure if >>>>> it's worth it. Opinions welcomed. If I am going to refactor, I would >>>>> prefer that be done as a next step so I'm not disturbing the existing >>>>> DCMDs with this first implementation. >>>>> >>>>> I added some comments to code only used for GC.class_stats and >>>>> GC.class_histogram. I did this when trying to figure them out so I >>>>> could better understand how to implement VM.class_hierarchy. I can >>>>> take them out if you think they are not appropriate for this commit. >>>>> >>>>> One other item I like to discuss is whether it is worth adding a >>>>> class name argument to this DCMD. That would cause just the >>>>> superclasses and subclasses of the named class to be printed. If you >>>>> think that is useful, I think it can be added without too much trouble. >>>>> >>>>> At the moment not much testing has been done other than running the >>>>> DCMD and looking at the output. I'll do more once it's clear the code >>>>> has "settled". I would like to know if there are any existing tests >>>>> for GC.class_stats and GC.class_histogram (there are none in the >>>>> "test" directory). If so, possibly one could serve as the basis for a >>>>> new test for VM.class_hierarchy. >>>>> >>>>> thanks, >>>>> >>>>> Chris >>> >> >> -- >> Frederic Parain - Oracle >> Grenoble Engineering Center - France >> Phone: +33 4 76 18 81 17 >> Email: frederic.par...@oracle.com >