JDK-8327246: Add a jcmd diagnostic command to list the jar files loaded by a process

This commit is contained in:
Larry Cable 2026-01-05 11:21:39 -08:00
parent 27dbdec297
commit 6ce88730f1
4 changed files with 49 additions and 8 deletions

View File

@ -35,6 +35,7 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verifier.hpp"
@ -2336,8 +2337,8 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
return nullptr;
}
PrintClassClosure::PrintClassClosure(outputStream* st, bool verbose)
:_st(st), _verbose(verbose) {
PrintClassClosure::PrintClassClosure(outputStream* st, bool verbose, bool location)
:_st(st), _verbose(verbose), _location(location) {
ResourceMark rm;
_st->print("%-18s ", "KlassAddr");
_st->print("%-4s ", "Size");
@ -2375,6 +2376,41 @@ void PrintClassClosure::do_klass(Klass* k) {
_st->print("%-7s ", buf);
// klass name
_st->print("%-5s ", k->external_name());
if (k->is_instance_klass() && _location) {
oop pd = java_lang_Class::protection_domain(k->java_mirror());
InstanceKlass* ik;
if (pd != nullptr && (ik = InstanceKlass::cast(pd->klass()))->is_instance_klass()) {
TempNewSymbol css = SymbolTable::new_symbol("codesource");
TempNewSymbol csss = SymbolTable::new_symbol("Ljava/security/CodeSource;");
fieldDescriptor csfd;
if (ik->find_field(css, csss, &csfd)) {
oop cs = pd->obj_field(csfd.offset());
if (cs != nullptr && (ik = InstanceKlass::cast(cs->klass()))->is_instance_klass()) {
fieldDescriptor locfd;
TempNewSymbol csls = SymbolTable::new_symbol("locationNoFragString");
TempNewSymbol cslss = SymbolTable::new_symbol("Ljava/lang/String;");
if (ik->find_field(csls, cslss, &locfd)) {
oop loc = cs->obj_field(locfd.offset());
if (loc != nullptr && loc->klass() == vmClasses::String_klass()) {
java_lang_String::print(loc, _st, MAXPATHLEN);
}
}
}
}
}
}
// end
_st->cr();
if (_verbose) {

View File

@ -1209,8 +1209,9 @@ class PrintClassClosure : public KlassClosure {
private:
outputStream* _st;
bool _verbose;
bool _location;
public:
PrintClassClosure(outputStream* st, bool verbose);
PrintClassClosure(outputStream* st, bool verbose, bool location);
void do_klass(Klass* k);
};

View File

@ -958,27 +958,30 @@ ClassesDCmd::ClassesDCmd(outputStream* output, bool heap) :
"C = marked with @Contended annotation, "
"R = has been redefined, "
"S = is shared class",
"BOOLEAN", false, "false") {
"BOOLEAN", false, "false"),
_location("-location", "print class file location url (if available)", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_verbose);
_dcmdparser.add_dcmd_option(&_location);
}
class VM_PrintClasses : public VM_Operation {
private:
outputStream* _out;
bool _verbose;
bool _location;
public:
VM_PrintClasses(outputStream* out, bool verbose) : _out(out), _verbose(verbose) {}
VM_PrintClasses(outputStream* out, bool verbose, bool location) : _out(out), _verbose(verbose), _location(location) {}
virtual VMOp_Type type() const { return VMOp_PrintClasses; }
virtual void doit() {
PrintClassClosure closure(_out, _verbose);
PrintClassClosure closure(_out, _verbose, _location);
ClassLoaderDataGraph::classes_do(&closure);
}
};
void ClassesDCmd::execute(DCmdSource source, TRAPS) {
VM_PrintClasses vmop(output(), _verbose.value());
VM_PrintClasses vmop(output(), _verbose.value(), _location.value());
VMThread::execute(&vmop);
}

View File

@ -737,8 +737,9 @@ public:
class ClassesDCmd : public DCmdWithParser {
protected:
DCmdArgument<bool> _verbose;
DCmdArgument<bool> _location;
public:
static int num_arguments() { return 1; }
static int num_arguments() { return 2; }
ClassesDCmd(outputStream* output, bool heap);
static const char* name() {
return "VM.classes";