src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java
Print this page
*** 20,69 ****
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! package jdk.internal.jshell.jdi;
import java.util.HashMap;
import java.util.Objects;
! import com.sun.jdi.ReferenceType;
! import java.util.List;
! import com.sun.jdi.VirtualMachine;
/**
* Tracks the state of a class.
*/
class ClassTracker {
- private final VirtualMachine vm;
private final HashMap<String, ClassInfo> map;
! ClassTracker(VirtualMachine vm) {
! this.vm = vm;
this.map = new HashMap<>();
}
/**
! * Associates a class name, class bytes, and ReferenceType.
*/
class ClassInfo {
! // The name of the class -- always set
private final String className;
// The corresponding compiled class bytes when a load or redefine
// is started. May not be the loaded bytes. May be null.
! private byte[] bytes;
// The class bytes successfully loaded/redefined into the remote VM.
private byte[] loadedBytes;
- // The corresponding JDI ReferenceType. Used by redefineClasses and
- // acts as indicator of successful load (null if not loaded).
- private ReferenceType rt;
-
private ClassInfo(String className) {
this.className = className;
}
String getClassName() {
--- 20,62 ----
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! package jdk.jshell;
+ import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects;
! import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
/**
* Tracks the state of a class.
*/
class ClassTracker {
private final HashMap<String, ClassInfo> map;
! ClassTracker() {
this.map = new HashMap<>();
}
/**
! * Associates a class name, class bytes (current and loaded).
*/
class ClassInfo {
! // The name of the class
private final String className;
// The corresponding compiled class bytes when a load or redefine
// is started. May not be the loaded bytes. May be null.
! private byte[] currentBytes;
// The class bytes successfully loaded/redefined into the remote VM.
private byte[] loadedBytes;
private ClassInfo(String className) {
this.className = className;
}
String getClassName() {
*** 72,109 ****
byte[] getLoadedBytes() {
return loadedBytes;
}
! byte[] getBytes() {
! return bytes;
}
! private void setBytes(byte[] potentialBytes) {
! this.bytes = potentialBytes;
}
! // The class has been successful loaded redefined. The class bytes
! // sent are now actually loaded.
! void markLoaded() {
! loadedBytes = bytes;
}
! // Ask JDI for the ReferenceType, null if not loaded.
! ReferenceType getReferenceTypeOrNull() {
! if (rt == null) {
! rt = nameToRef(className);
! }
! return rt;
}
! private ReferenceType nameToRef(String name) {
! List<ReferenceType> rtl = vm.classesByName(name);
! if (rtl.size() != 1) {
! return null;
}
! return rtl.get(0);
}
@Override
public boolean equals(Object o) {
return o instanceof ClassInfo
--- 65,96 ----
byte[] getLoadedBytes() {
return loadedBytes;
}
! byte[] getCurrentBytes() {
! return currentBytes;
}
! void setCurrentBytes(byte[] bytes) {
! this.currentBytes = bytes;
}
! void setLoadedBytes(byte[] bytes) {
! this.loadedBytes = bytes;
}
! boolean isLoaded() {
! return loadedBytes != null;
}
! boolean isCurrent() {
! return Arrays.equals(currentBytes, loadedBytes);
}
!
! ClassBytecodes toClassBytecodes() {
! return new ClassBytecodes(className, currentBytes);
}
@Override
public boolean equals(Object o) {
return o instanceof ClassInfo
*** 114,128 ****
public int hashCode() {
return Objects.hashCode(this.className);
}
}
// Map a class name to the current compiled class bytes.
! ClassInfo classInfo(String className, byte[] bytes) {
ClassInfo ci = get(className);
! ci.setBytes(bytes);
! return ci;
}
// Lookup the ClassInfo by class name, create if it does not exist.
ClassInfo get(String className) {
return map.computeIfAbsent(className, k -> new ClassInfo(k));
--- 101,129 ----
public int hashCode() {
return Objects.hashCode(this.className);
}
}
+ void markLoaded(ClassBytecodes[] cbcs) {
+ for (ClassBytecodes cbc : cbcs) {
+ get(cbc.name).setLoadedBytes(cbc.bytecodes);
+ }
+ }
+
+ void markLoaded(ClassBytecodes[] cbcs, boolean[] isLoaded) {
+ for (int i = 0; i < cbcs.length; ++i) {
+ if (isLoaded[i]) {
+ ClassBytecodes cbc = cbcs[i];
+ get(cbc.name).setLoadedBytes(cbc.bytecodes);
+ }
+ }
+ }
+
// Map a class name to the current compiled class bytes.
! void setCurrentBytes(String className, byte[] bytes) {
ClassInfo ci = get(className);
! ci.setCurrentBytes(bytes);
}
// Lookup the ClassInfo by class name, create if it does not exist.
ClassInfo get(String className) {
return map.computeIfAbsent(className, k -> new ClassInfo(k));