# Kernel Extension Points
Zephyr was designed with extreme extensibility and customizability in mind. Zephyr's internal behaviors can be
modified in a variety of ways, including plugins
, kernel entry points
, and kernel modules
# Kernel Entry Points
Kernel Entry Points are the lowest-level mechanism to extend or modify Zephyr's internal behavior. Kernel Entry Points
are added to the $ZEPHYR_HOME/lib
directory, and so are available on the System classloader, in contrast to the other mechanisms.
# The Kernel Entry Point API
To modify Kernel behaviors, you must implement some portion of the Kernel EntryPoint
API, defined in kernel-api
.
public interface EntryPoint extends PrioritizedExtension, Startable, Stoppable {
enum ContextEntries {
ARGS,
ENTRY_POINTS,
ENTRY_POINTS_TEMP,
KERNEL_EXECUTOR_SERVICE,
ENTRY_POINT_REGISTRY;
}
Logger getLogger();
default void initialize(Map<ContextEntries, Object> context) {}
default void finalize(Map<ContextEntries, Object> context) {}
default void start() {
getLogger().log(Level.INFO, "entry point starting...");
}
default void stop() {
getLogger().log(Level.INFO, "entry point stopping...");
}
default <T> T getService(Class<T> type) {
throw new UnsupportedOperationException("Empty Entry Point contains no services");
}
default <T> boolean exports(Class<T> type) {
return false;
}
default void run(Map<ContextEntries, Object> ctx) {}
Options<?> getOptions();
}
An EntryPoint
may obtain the parameters used to start the Zephyr process via the context
map supplied to initialize
and
use them to modify its behavior, ideally creating and supplying an implementation of io.zephyr.kernel.Options
( Picocli (opens new window) is available
as an EntryPoint
by default.)
EntryPoints may provide additional Zephyr Shell commands, modify the shell, modify the internal concurrency mechanisms, alter logging, and many other things.
# Entry Point Concurrency
Each EntryPoint is run asynchronously relative to the main Zephyr thread, but does not guarantee a unique ThreadLocal context. Implementors should
use concurrency with caution. Zephyr supplies an ExecutorService, available in the context under the key KERNEL_EXECUTOR_SERVICE
. Any tasks scheduled on the ExecutorService
must complete before stop
is exited.
EntryPoint's initialize
and finalize
methods must not block for long periods. However, run
may block for as long as it needs to, but should
honor OS shutdown requests.
Finally, EntryPoints do not need to be thread-safe.
# Entry Point Order
The kernel launcher is itself an entry point, and has priority MAX_PRIORITY - 10
, allowing other entry points to preempt it.
Preempting the launcher should be done with care, if at all.
# Kernel Modules
Once Zephyr has scheduled and executed all available entry points, kernel modules
are loaded and executed. All
kernel modules reside in the kernel classloader
, which is an optional predecessor to any plugin classloader graph
Kernel modules don't have a defined lifecycle, and generally exist to supply various Java Service Provider Interfaces
that modify the kernel's capabilities for interacting with
plugins. For instance, to define a new packaging format, a kernel module may implement the io.zephyr.kernel.extensions.ModuleAssemblyExtractor
API.
public interface ModuleAssemblyExtractor {
void extract(Assembly assembly, FileSystem moduleFilesystem, ExtractionListener listener)
throws Exception;
interface ExtractionListener {
void beforeEntryExtracted(String name, Object target);
void afterEntryExtracted(String name, Object target);
}
}
# Kernel Module Concurrency
Kernel modules are safely and concurrently executed on the Gyre, and do not require any internal thread-safety mechanisms. Zephyr APIs are thread-safe.