RFR(S): 8244203: sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java fails with NullPointerException
Chris Plummer
chris.plummer at oracle.com
Thu May 21 19:10:00 UTC 2020
Yes, you are correct. As I mentioned earlier, it turns out this
functionality isn't used, other wise it also would have been exposed by
the other bug I fixed (the unnecessary outter loop). I'll fix this to
use !isLoaded().
thanks,
Chris
On 5/21/20 10:44 AM, Daniil Titov wrote:
> Hi Chris,
>
> I have a question about a change in
> src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java.
>
> 61 /** All classes, and their initiating class loader, passed in. */
> 62 public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v, Oop loader) {
> 63 int tblSize = tableSize();
> 64 for (int index = 0; index < tblSize; index++) {
> 65 for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
> 66 probe = (DictionaryEntry) probe.next()) {
> 67 Klass k = probe.klass();
> 68 // Only visit InstanceKlasses that are at least in the "loaded" init_state. Otherwise
> 69 // the InstanceKlass won't have some required fields initialized, which can cause problems.
> 70 if (k instanceof InstanceKlass && ((InstanceKlass)k).isLoaded()) {
> 71 continue;
> 72 }
> 73 v.visit(k, loader);
> 74 }
> 75 }
> 76 }
>
>
> Based on the comment at lines 68-69 should not condition on line 70 be
>
> 70 if (k instanceof InstanceKlass && !((InstanceKlass)k).isLoaded()) {
>
> in order to we skip InstanceKlasses that are not in the "loaded" state?
>
> Thank you,
> Daniil
>
> On 5/19/20, 12:47 PM, "serviceability-dev on behalf of Chris Plummer" <serviceability-dev-bounces at openjdk.java.net on behalf of chris.plummer at oracle.com> wrote:
>
> Hello,
>
> Please review the following:
>
> http://cr.openjdk.java.net/~cjplummer/8244203/webrev.00/index.html
> https://bugs.openjdk.java.net/browse/JDK-8244203
>
> The root of the problem is that SA is trying iterate over all loaded
> classes by using ClassLoaderDataGraph, but it possible that a class that
> ClassLoaderDataGraph knows about can be in a state that makes it
> findable by SA, but not yet initialized far enough to make is usable by SA.
>
> The first issue I tracked down in this area was a case where an
> InstanceKlass did not yet have its java_mirror. This resulted in the NPE
> you see reported in the bug, because there is some SA code that assumes
> all InstanceKlass's have a java_mirror. I fixed this by not having
> ClassLoaderData.classesDo() return any InstanceKlass that was not yet
> initialized to the point of being considered "loaded". That fixed this
> particular problem, but there was another still lurking that was similar..
>
> The second issue was that event attempting to iterate over the set of
> loaded classes could cause an NPE, so you couldn't even get to the point
> of being able to reject an InstanceKlass if it was not yet int he
> "loaded" state. ClassLoaderData.classesDo() needs to get the first
> Klass in its list:
>
> public void classesDo(ClassLoaderDataGraph.ClassVisitor v) {
> for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
> v.visit(l);
> }
> }
>
> Since the first Klass is the one most recently added, its also subject
> to sometimes not yet being fully loaded. Calling getKlasses() will
> instantiate (wrap) the first Klass in the list, which in this case is a
> partially loaded InstanceKlass which was so early in its initialization
> that InstanceKlass::_fields had not yet been setup. Creating an
> InstanceKlass (on the SA side) requires _fields to be set, otherwise it
> gets an NPE. I fixed this by allowing the InstanceKlass to still be
> created if not yet "loaded", but skipped any further initialization of
> the InstanceKlass that would rely on _fields. This allows the
> InstanceKlass to still be used by ClassLoaderData.classesDo() to iterate
> over the classes. However, I also wanted to make sure this uninitialized
> InstanceKlass wasn't leaked out to SA beyond its use by classesDo(). It
> looks like the only other way this is possible is with
> ClassLoaderData.find() and Dictionary.allEntriesDo(), so I put an
> InstanceKlass.isLoaded() checks there also.
>
> One way I tested these fixes was to by introducing short sleep in
> ClassFileParser::fill_instance_klass() right after the Klass gets added
> to the ClassLoaderData:
>
> _loader_data->add_class(ik, publicize);
> + os::naked_short_sleep(2);
>
> By doing this the bug reproduced almost every time, and the fixes
> resolved it.
>
> You'll also notice a bug fix in ClassLoaderData.allEntriesDo(). The
> outside loop is not only unnecessary, but results in the same Klass
> being visited multiple times. It turns out no one uses this
> functionality, but I fixed it anyway rather than rip it out because it
> seemed it might be useful in the future.
>
> The changes in ClhsdbClasses.java test are to better check for expected
> classes when dumping the set of all classes. I added these after
> realizing I had introduced a bug that caused only InstanceKlasses to be
> dumped, not interfaces or arrays, so I added a few more types to the
> list that we check.
>
> thanks,
>
> Chris
>
>
>
>
More information about the serviceability-dev
mailing list