JAR and script reloading
This page describes editor-time reloading of JVM scripts. Exported games do not reload source files or JAR registrations this way.
Mental model
A JvmScript can start from either side of the integration:
- A physical script is a real Godot resource such as
res://game/Foo.kt. It is created by the resource loader and is the resource Godot attaches to nodes. - A virtual script is created from a
KtClassread from the project JAR. It has ajvm://path and exists when Godot knows the registered class before it has a matching source resource.
The fully qualified class name (FQCN) is the identity that joins them. A physical and virtual script with the same FQCN represent one script, never two. When they meet, the physical resource becomes canonical because Godot owns it.
The manager maintains two different views:
- registered name -> script: the classes in the current JAR;
- FQCN -> script: every live physical or virtual script with a known FQCN.
The FQCN map is weak. Godot or another resource owns the script itself; the manager only indexes it.
Resource loading
For a normal res:// load, JvmResourceFormatLoader reads the source, parses
its FQCN, and creates or binds the physical script. A jvm:// load only
resolves an already registered virtual script by its filename; it never reads
or creates a file.
CACHE_MODE_IGNORE is used by the Script editor to inspect an externally
changed file. When the JVM script is already cached, the loader calls that
script's reload_from_file() and returns it. This deliberately refreshes the
canonical physical script rather than creating a temporary JVM script.
JAR reload
A JAR reload refreshes registrations, not source files.
- Clear the current registered-name map and JVM class indices.
- Clear the old
KtClassfrom every live FQCN candidate. The script resource and its FQCN identity remain available. - For every
KtClassin the new JAR, find its FQCN candidate. Reuse it when present; otherwise create a virtual script. - Rebuild the registered-name map and JVM class indices from those new
KtClassobjects. - Remove dead weak FQCN entries.
This retains a physical source resource even when one JAR build temporarily does not contain its class. It also retains externally owned virtual resources so a later JAR build or source reload can reuse them.
Physical source reload
Godot calls JvmScript::reload_from_file() for an already loaded source
resource. It rereads the file, stores the source text, records the source file
modification time, parses its FQCN, and updates the manager's physical-script
mapping.
The reconciliation rules are:
- Same FQCN and already canonical: no manager change is required.
- FQCN changed: detach the old
KtClassinto a virtual script so the old JAR class remains represented. - No parsed FQCN: leave the physical script unbound until a valid reload.
- Matching virtual script: promote the physical script, move its
KtClass, migrate placeholders and exported values, and updateTypeManager. - Matching orphan virtual script: do not promote it because it has no
KtClassto transfer; make the physical script the FQCN mapping and wait for a JAR containing that class. - Matching different physical script: report a duplicate FQCN error.
- No match: make this physical script the FQCN mapping.
Source warning
The node warning is timestamp-based, not a reload-order flag. Each physical
script stores the source file modification time when it is loaded, saved, or
reloaded. The manager records the current time when it reloads main.jar. A
placeholder warns only when its source timestamp is newer than the JAR reload
timestamp. Reloading either resource therefore gives the same result regardless
of which one Godot processes first.
Reload order
The order does not matter:
- Source first: the physical script enters the FQCN map; the next JAR
reload binds the new
KtClassto it. - JAR first: the JAR may create a virtual script; the following physical source reload promotes the physical resource and removes that virtual twin.
An empty or invalid source has no FQCN and is intentionally not mapped. Once it becomes valid and reloads, it follows the normal physical-source rules.