3.8 KiB
3.8 KiB
Class Loading and Boot Image
Location: crates/core/src/class_loader.rs, crates/core/src/bimage.rs
Boot Image (Bimage)
A 7z archive containing precompiled Java standard library classes.
Structure
pub struct Bimage {
image: ArchiveReader<File>, // 7z archive reader
modules: Vec<String>, // Available modules
packages: HashMap<String, String>, // Package -> Module mapping
pub total_access_time: Duration, // Performance tracking
}
- Default Location:
./lib/modules - Format: 7z compressed archive
- Structure:
<module>/classes/<class>.class - Default Module:
java.base(used when no module is specified)
Class Loading Flow
The ClassLoader manages class resolution with a two-tier fallback mechanism:
Process
- Check Cache: Look in
DashMap<(String, LoaderId), Arc<RuntimeClass>>for already-loaded classes - Try Bimage: Attempt to load from boot image via
bimage.get_class(module, class_fqn) - Fallback to Disk: If not in bimage, load from filesystem at
{CLASSPATH}/{class_name}.class - Parse & Cache: Parse ClassFile using deku, create RuntimeClass, store in cache
Key Method
pub fn load_class(&mut self, what: &str, loader: LoaderId) -> Result<Arc<RuntimeClass>, VmError> {
let bytes = self.bimage
.and_then(|b| b.get_class("", what).ok())
.or_else(|_| Self::load_class_from_disk(what))
.map_err(|_| VmError::LoaderError(...))?;
let (_, cf) = ClassFile::from_bytes(bytes.as_ref())?;
let runtime = self.runtime_class(cf);
// Store with loader ID for multi-loader support
self.classes.insert((class_fqn, loader), Arc::new(runtime));
}
Classpath Handling
Resolution Priority
- Bimage (boot image) - Primary source for standard library
- Command-line argument (arg[1]) - User-provided classpath
- Default
./datadirectory - Fallback location
Implementation
fn load_class_from_disk(what: &str) -> Result<Vec<u8>, String> {
let class_path = std::env::args()
.nth(1)
.unwrap_or("./data".to_string())
.replace("\\", "/");
let path = format!("{class_path}/{what}.class");
// Load file from disk
}
Bootstrap Process
Location: crates/core/src/vm.rs - boot_strap() method
Steps
- Create VM:
ClassLoader::with_bimage()- initializes with boot image - Load Core Classes: Preloads essential VM classes
- Create Primitive Classes: Synthetic class objects for primitive types
- Initialize Classes: Run static initializers (
<clinit>)
Core Classes Loaded
let classes = vec![
"java/lang/String",
"java/lang/System",
"java/lang/Class",
"java/lang/Object",
"java/lang/Thread",
"java/lang/ThreadGroup",
"java/lang/Module",
"java/lang/reflect/Method",
// ...
];
RuntimeClass
Runtime representation of a loaded class:
Cached Data
- Superclass Chain:
super_classes: Vec<Arc<RuntimeClass>> - Interface Hierarchy:
super_interfaces: Vec<Arc<RuntimeClass>> - Component Type: For array classes, reference to element type
- Initialization State: Thread-safe
InitStateenum
Initialization States
pub enum InitState {
NotInitialized,
Initializing(ThreadId), // Track which thread is initializing
Initialized,
}
Method/Field Resolution
find_method()- Searches class then walks up superclass chainfind_field()- Same recursive behavior for fieldsis_assignable_into()- Checks type compatibility with array covariance
Multi-Loader Support
Classes are keyed by (class_name, LoaderId) tuple to support:
- Different class loaders loading same-named classes
- Isolation between class loader namespaces
- Proper class identity checks