8168914: Crash in ClassLoaderData/JNIHandleBlock::oops_do during concurrent marking

Reviewed-by: dholmes, tschatzl, coleenp, kbarrett, eosterlund, stefank
This commit is contained in:
Erik Helin 2017-02-23 18:57:10 +01:00
parent 86a9ef8d83
commit 4145e90718
3 changed files with 115 additions and 33 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -52,7 +52,6 @@
class ClassLoaderData;
class JNIMethodBlock;
class JNIHandleBlock;
class Metadebug;
class ModuleEntry;
class PackageEntry;
@ -160,6 +159,34 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void oops_do(OopClosure* f);
};
class ChunkedHandleList VALUE_OBJ_CLASS_SPEC {
struct Chunk : public CHeapObj<mtClass> {
static const size_t CAPACITY = 32;
oop _data[CAPACITY];
volatile juint _size;
Chunk* _next;
Chunk(Chunk* c) : _next(c), _size(0) { }
};
Chunk* _head;
void oops_do_chunk(OopClosure* f, Chunk* c, const juint size);
public:
ChunkedHandleList() : _head(NULL) {}
~ChunkedHandleList();
// Only one thread at a time can add, guarded by ClassLoaderData::metaspace_lock().
// However, multiple threads can execute oops_do concurrently with add.
oop* add(oop o);
#ifdef ASSERT
bool contains(oop* p);
#endif
void oops_do(OopClosure* f);
};
friend class ClassLoaderDataGraph;
friend class ClassLoaderDataGraphKlassIteratorAtomic;
friend class ClassLoaderDataGraphMetaspaceIterator;
@ -185,8 +212,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
volatile int _claimed; // true if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
// Has to be an int because we cas it.
JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which
// have the same life cycle of the corresponding ClassLoader.
ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which
// have the same life cycle of the corresponding ClassLoader.
Klass* volatile _klasses; // The classes defined by the class loader.
PackageEntryTable* volatile _packages; // The packages defined by the class loader.
@ -217,9 +244,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies);
~ClassLoaderData();
JNIHandleBlock* handles() const;
void set_handles(JNIHandleBlock* handles);
// GC interface.
void clear_claimed() { _claimed = 0; }
bool claimed() const { return _claimed == 1; }
@ -312,7 +336,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
const char* loader_name();
jobject add_handle(Handle h);
void remove_handle(jobject h);
void remove_handle_unsafe(jobject h);
void add_class(Klass* k, bool publicize = true);
void remove_class(Klass* k);
bool contains_klass(Klass* k);