compatibility-13/src/com/jetbrains/sa/jdi/CompatibilityHelper13.java (107 lines of code) (raw):
/*
* Copyright (C) 2018 JetBrains s.r.o.
*
* This program is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public License v2 with Classpath Exception.
* The text of the license is available in the file LICENSE.TXT.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.TXT for more details.
*
* You may contact JetBrains s.r.o. at Na Hřebenech II 1718/10, 140 00 Prague,
* Czech Republic or at legal@jetbrains.com.
*/
package com.jetbrains.sa.jdi;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.JavaThread;
import sun.jvm.hotspot.runtime.Threads;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.utilities.KlassArray;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("unused")
class CompatibilityHelper13 implements Compatibility {
@Override
public Address getAddress(Method method) {
return method.getAddress();
}
@Override
public Address getAddress(Klass klass) {
return klass.getAddress();
}
@Override
public Klass asKlass(Oop ref) {
return java_lang_Class.asKlass(ref);
}
@Override
public List<InstanceKlass> getTransitiveInterfaces(InstanceKlass saKlass) {
List<InstanceKlass> res = new ArrayList<>();
KlassArray interfaces = saKlass.getTransitiveInterfaces();
int n = interfaces.length();
for (int i = 0; i < n; i++) {
res.add((InstanceKlass) interfaces.getAt(i));
}
return res;
}
@Override
public String getSourceDebugExtension(InstanceKlass saKlass) {
return saKlass.getSourceDebugExtension();
}
@Override
public InstanceKlass getMethodHandleKlass() {
return SystemDictionary.getMethodHandleKlass();
}
@Override
public Klass getMethodHolder(Method method) {
return method.getMethodHolder();
}
private static final long compressedKlassOffset;
private static final long klassOffset;
static {
long coff = -1;
long koff = -1;
try {
java.lang.reflect.Field field = Oop.class.getDeclaredField("klass");
field.setAccessible(true);
coff = ((MetadataField) field.get(null)).getOffset();
java.lang.reflect.Field field1 = Oop.class.getDeclaredField("compressedKlass");
field1.setAccessible(true);
koff = ((MetadataField) field1.get(null)).getOffset();
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
compressedKlassOffset = coff;
klassOffset = koff;
}
@Override
public Address getKlassAddress(Oop oop) {
if (VM.getVM().isCompressedKlassPointersEnabled()) {
return oop.getHandle().getCompKlassAddressAt(compressedKlassOffset);
} else {
return oop.getHandle().getAddressAt(klassOffset);
}
}
@Override
public List<Klass> allClasses(SystemDictionary systemDictionary, VM vm) {
List<Klass> saKlasses = new ArrayList<>();
vm.getClassLoaderDataGraph().classesDo(k -> {
// for non-array classes filter out un-prepared classes
// refer to 'allClasses' in share/back/VirtualMachineImpl.c
if (k instanceof ArrayKlass) {
saKlasses.add(k);
} else {
int status = k.getClassStatus();
if ((status & JVMDIClassStatus.PREPARED) != 0) {
saKlasses.add(k);
}
}
});
return saKlasses;
}
@Override
public List<ReferenceTypeImpl> visibleClasses(final Oop ref, final VirtualMachineImpl vm) {
List<ReferenceTypeImpl> res = new ArrayList<>();
vm.saVM().getClassLoaderDataGraph().allEntriesDo((k, loader) -> {
if (ref.equals(loader)) {
res.add(vm.referenceType(k));
}
});
return res;
}
@Override
public List<JavaThread> getThreads(VM vm) {
List<JavaThread> res = new ArrayList<>();
Threads threads = vm.getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
res.add(threads.getJavaThreadAt(i));
}
return res;
}
}