Class ExecutionEnvironment
- All Implemented Interfaces:
IExecutionEnvironment
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate IModule
private String[]
private IModule
private IProject
private IModule
private TypeSystemState
static final String
private int
Detect whether or not the jdwp agent is alive in this process, if so start a thread that wakes up every N seconds and checks to see if the ReloadClassesIndicator Java class has been redefined by a debugger.private static final IProject
private static final Map<Object,
ExecutionEnvironment> "Special" java classes that will be used to locate "special" JARs which should be included in the classpath.private static ExecutionEnvironment
Fields inherited from interface gw.lang.reflect.module.IExecutionEnvironment
DEFAULT_SINGLE_MODULE_NAME, GLOBAL_MODULE_NAME
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid
(package private) void
checkForDuplicates
(String moduleName) static List<IDirectory>
private static List<IDirectory>
static Collection<? extends IExecutionEnvironment>
getAll()
private int
String[]
This method is a hack to resolve "special" system-like classes provided by execution environment.getState()
void
initializeCompiler
(GosucModule gosucModule) void
initializeDefaultSingleModule
(List<? extends GosuPathEntry> pathEntries, List<IDirectory> backingSourceEntries, String... discretePackages) void
initializeMultipleModules
(List<? extends IModule> modules) void
initializeSimpleIde
(GosucModule gosucModule) static ExecutionEnvironment
instance()
static ExecutionEnvironment
private boolean
isInModule
(IModule module, IResource file) boolean
makeGosucProjectFile
(String projectClassName) private static String
removeAllQuotes
(String classpath) void
removeModule
(IModule module) void
renameModule
(IModule module, String newName) void
setDiscretePackages
(String[] discretePackages) void
shutdown()
private void
void
void
void
void
-
Field Details
-
DEFAULT_PROJECT
-
INSTANCES
-
THE_ONE
-
CLASS_REDEFINER_THREAD
- See Also:
-
SPECIAL_CLASSES
"Special" java classes that will be used to locate "special" JARs which should be included in the classpath. This is a replacement to old SPECIAL_FILES variable. -
_project
-
_modules
-
_defaultModule
-
_jreModule
-
_rootModule
-
_discretePackages
-
_state
-
counter
private int counterDetect whether or not the jdwp agent is alive in this process, if so start a thread that wakes up every N seconds and checks to see if the ReloadClassesIndicator Java class has been redefined by a debugger. If so, it reloads Gosu classes that have changed.Why, you ask? Well since Gosu classes are not compiled to disk, the IDE hosting Gosu can't simply send the bytes in a conventional JDI redefineClasses() call. Yet it somehow needs to at least inform Gosu's type system in the target process that Gosu classes have changed. The JVMTI doesn't offer much help; there's no way to field an arbitrary call from the JDWP client, or for the client to send an arbitrary message. Nor is it possible to leverage the JVMTI's ability to handle method invocation etc. because the target thread must be suspended at a breakpoint, which is not necessarily the case during compilation, and certainly isn't the case for a thread dedicated to fielding such a call. What to do?
We can leverage redefineClasses() after all. The idea is for the IDE compiler to redefine a class (via asm) designated as the "ReloadClassIndicator". This class lives inside Gosu's type system. It has a single method: public static long timestamp() and returns a literal value. If the target process is being debugged (jdwp agent detection), a thread in the target process starts immediately and waits a few seconds before calling the timestamp() method, it does this in a forever loop. If the timestamp value changes, we assume the IDE redefined the class with a new value to indicate classes have changed. In turn we find and reload changed classes. What could be more straight forward?
An alternative approach would be for the IDE to establish an additional line of communication with the target process e.g., socket, memory, whatever. But that is messy (requires config on user's end) and error prone. One debug socket is plenty.
Improvements to this strategy include supplying not only an indication that stuff has changed, but also the names of the classes that have changed. This would releive the target process from having to keep track timestamps on all loaded classes. This could be implemented by having the class return an array of names. An even better improvement would be to include not just the names, but also the source of the classes. This would enable the debuger to modify in memory the classes during a remote debugging session.
-
-
Constructor Details
-
ExecutionEnvironment
-
-
Method Details
-
instance
-
instance
-
getAll
-
getProject
- Specified by:
getProject
in interfaceIExecutionEnvironment
-
getModules
- Specified by:
getModules
in interfaceIExecutionEnvironment
-
initializeDefaultSingleModule
public void initializeDefaultSingleModule(List<? extends GosuPathEntry> pathEntries, List<IDirectory> backingSourceEntries, String... discretePackages) -
uninitializeDefaultSingleModule
public void uninitializeDefaultSingleModule() -
initializeMultipleModules
-
uninitializeMultipleModules
public void uninitializeMultipleModules() -
addModule
- Specified by:
addModule
in interfaceIExecutionEnvironment
-
initializeCompiler
-
uninitializeCompiler
public void uninitializeCompiler() -
initializeSimpleIde
-
uninitializeSimpleIde
public void uninitializeSimpleIde() -
checkForDuplicates
-
getDiscretePackages
-
setDiscretePackages
-
removeModule
- Specified by:
removeModule
in interfaceIExecutionEnvironment
-
getModule
- Specified by:
getModule
in interfaceIExecutionEnvironment
-
getModule
- Specified by:
getModule
in interfaceIExecutionEnvironment
-
isInModule
-
getModule
- Specified by:
getModule
in interfaceIExecutionEnvironment
-
createJreModule
- Specified by:
createJreModule
in interfaceIExecutionEnvironment
-
getJreModule
- Specified by:
getJreModule
in interfaceIExecutionEnvironment
- Returns:
- The module responsible for resolving JRE core classes e.g., java.lang.* etc. Note in default single module environment this is the single module, otherwise this is the module create by calling createJreModule(). This method will never return null but it will throw an NPE if the JRE module is null.
-
getGlobalModule
- Specified by:
getGlobalModule
in interfaceIExecutionEnvironment
-
findRootModule
-
getState
- Specified by:
getState
in interfaceIExecutionEnvironment
-
renameModule
- Specified by:
renameModule
in interfaceIExecutionEnvironment
-
makeGosucProjectFile
- Specified by:
makeGosucProjectFile
in interfaceIExecutionEnvironment
-
shutdown
public void shutdown() -
getCounter
private int getCounter() -
startSneakyDebugThread
private void startSneakyDebugThread() -
createDefaultClassPath
-
removeAllQuotes
-
expand
-
isShadowingMode
public boolean isShadowingMode()- Specified by:
isShadowingMode
in interfaceIExecutionEnvironment
-
getJarsContainingSpecialClasses
This method is a hack to resolve "special" system-like classes provided by execution environment. This is the replacement of old addSpecialJars() method
-