-
-
Notifications
You must be signed in to change notification settings - Fork 923
LoadService loading mechanism
JRuby uses LoadService as the main mechanism of loading files for Kernel.require and Kernel.load.
-
Kernel.require is handled by LoadService.require method and Kernel.load is handled by LoadService.load method.
-
Both methods create a SearchState object to reflect the search strategy (which boils down to which suffixes ought to be used for the search) and try to find a matching Library with findLibraryBySearchState.
-
findLibraryBySearchState primarily relies on LibrarySearcher.findBySearchState to resolve paths, but we also use findLibraryWithClassloaders until file resources fully support
classpath:/
based paths. -
findBySearchState attempts to locate a library by iterating over suffixes from the searchState and attempting to load one of three following libraries:
- Builtin libraries, which are registered with
LoadService
usingaddBuiltinLibrary
. - A ResourceLibrary that is backed by a FileResource. See next section for details.
- ClassExtensionLibrary that looks for FooService java class that implements BasicLibraryService for loading.
If a match is found, it is immediately returned.
- If a library is found, it gets loaded via its
load
method.
ResourceLibrary is located by the findResourceLibrary method. This is the flow that handles the 'regular' ruby loading semantics, so we have to consider path special cases as well as LOAD_PATH:
- If path starts with ./ or ../, starts with a schema (e.g. file: or jar:) or java.lang.File.isAbsolute returns true for the path, we bypass load paths and treat the path as-is.
- If path starts with ~/, we replace ~/ with value of ENV["HOME"] and bypass loads paths.
- Any other cases we iterate over the LOAD_PATH array and look for (LOAD_PATH_ENTRY + "/" + path) path.
After the path mangling step, we create a resource with JRubyFile.createResource. If the return resource actually exists, we return ResourceLibrary that handles the specific of the load or return null if resource points to a non-existent resource.
There are three load strategies for loading libraries backed by a resource:
-
If path ends with ".jar" (e.g. /foo/bar/lib.jar) we handle it as a 'jar' load. That means adding the path to the jar to the classloader classpath and also attempting to load accompanying
BasicLibraryService
(e.g. /LibService.class). -
If path ends with ".class" we treat it as a compiled script, and use
CompiledScriptLoader
to load. -
In any other cases, we load the script with
Ruby.loadFile
.