src/jdk.jshell/share/classes/jdk/jshell/Unit.java
Print this page
@@ -30,15 +30,20 @@
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
+import jdk.jshell.ClassTracker.ClassInfo;
import jdk.jshell.Snippet.Kind;
import jdk.jshell.Snippet.Status;
import jdk.jshell.Snippet.SubKind;
import jdk.jshell.TaskFactory.AnalyzeTask;
import jdk.jshell.TaskFactory.CompileTask;
+import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
+import jdk.jshell.spi.ExecutionControl.ClassInstallException;
+import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
+import jdk.jshell.spi.ExecutionControl.NotImplementedException;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
import static jdk.jshell.Snippet.Status.OVERWRITTEN;
@@ -73,11 +78,11 @@
private DiagList recompilationDiagnostics = null;
private List<String> unresolved;
private SnippetEvent replaceOldEvent;
private List<SnippetEvent> secondaryEvents;
private boolean isAttemptingCorral;
- private List<String> toRedefine;
+ private List<ClassInfo> toRedefine;
private boolean dependenciesNeeded;
Unit(JShell state, Snippet si, Snippet causalSnippet,
DiagList generatedDiagnostics) {
this.state = state;
@@ -259,49 +264,64 @@
boolean isDefined() {
return status.isDefined();
}
/**
- * Process the class information from the last compile.
- * Requires loading of returned list.
+ * Process the class information from the last compile. Requires loading of
+ * returned list.
+ *
* @return the list of classes to load
*/
- Stream<String> classesToLoad(List<String> classnames) {
+ Stream<ClassBytecodes> classesToLoad(List<String> classnames) {
toRedefine = new ArrayList<>();
- List<String> toLoad = new ArrayList<>();
+ List<ClassBytecodes> toLoad = new ArrayList<>();
if (status.isDefined() && !isImport()) {
// Classes should only be loaded/redefined if the compile left them
// in a defined state. Imports do not have code and are not loaded.
for (String cn : classnames) {
- switch (state.executionControl().getClassStatus(cn)) {
- case UNKNOWN:
+ ClassInfo ci = state.classTracker.get(cn);
+ if (ci.isLoaded()) {
+ if (ci.isCurrent()) {
+ // nothing to do
+ } else {
+ toRedefine.add(ci);
+ }
+ } else {
// If not loaded, add to the list of classes to load.
- toLoad.add(cn);
+ toLoad.add(ci.toClassBytecodes());
dependenciesNeeded = true;
- break;
- case NOT_CURRENT:
- // If loaded but out of date, add to the list of classes to attempt redefine.
- toRedefine.add(cn);
- break;
- case CURRENT:
- // Loaded and current, so nothing to do
- break;
}
}
}
return toLoad.stream();
}
/**
- * Redefine classes needing redefine.
- * classesToLoad() must be called first.
+ * Redefine classes needing redefine. classesToLoad() must be called first.
+ *
* @return true if all redefines succeeded (can be vacuously true)
*/
boolean doRedefines() {
- return toRedefine.isEmpty()
- ? true
- : state.executionControl().redefine(toRedefine);
+ if (toRedefine.isEmpty()) {
+ return true;
+ }
+ ClassBytecodes[] cbcs = toRedefine.stream()
+ .map(ci -> ci.toClassBytecodes())
+ .toArray(size -> new ClassBytecodes[size]);
+ try {
+ state.executionControl().redefine(cbcs);
+ state.classTracker.markLoaded(cbcs);
+ return true;
+ } catch (ClassInstallException ex) {
+ state.classTracker.markLoaded(cbcs, ex.installed());
+ return false;
+ } catch (EngineTerminationException ex) {
+ state.closeDown();
+ return false;
+ } catch (NotImplementedException ex) {
+ return false;
+ }
}
void markForReplacement() {
// increment for replace class wrapper
si.setSequenceNumber(++seq);