forked from jnode/jnode
-
Notifications
You must be signed in to change notification settings - Fork 0
Code Conventions
Levente Santha edited this page May 9, 2026
·
1 revision
JNode coding standards, patterns, and anti-patterns. Follow these when contributing to maintain consistency across the ~3,300 Java source files.
| Rule | Detail |
|---|---|
| Java target | 1.6 (no lambdas, no try-with-resources, no diamond operator, no multi-catch) |
| File encoding | US-ASCII only |
| Formatter |
jnode-eclipse-formatter-settings.xml in repo root |
| License header | LGPL 2.1, present in all source files |
Since JNode targets Java 1.6, do not use:
- Lambda expressions (
->) - Method references (
Class::method) - Diamond operator (
new ArrayList<>()) - Try-with-resources (
try (...)) - Multi-catch (
catch (A | B e)) -
String.isEmpty()is available (Java 1.6+) — prefer it over.length() == 0 -
@Overrideon interface methods (allowed only from Java 1.6+, use cautiously) -
java.util.Objects(Java 1.7+) -
java.nio.filepackage (Java 1.7+)
JNode defines custom annotations that control JIT compiler and VM behavior. These are critical to understand:
| Annotation | Meaning |
|---|---|
@Uninterruptible |
No GC safepoints, no thread switching. Use in kernel/scheduler code. |
@KernelSpace |
Method runs in kernel privilege context |
@Internal |
Not part of public API, may change without notice |
@SharedStatics |
Static fields shared across all isolates (default: per-isolate) |
@LoadStatics |
Re-initialize statics at boot time (vs. using build-time values) |
@MagicPermission |
Class is allowed to use VmMagic / Unsafe operations |
@PrivilegedActionPragma |
Method treated as a privileged action |
@Inline |
Hint to JIT: inline this method |
@NoInline |
Hint to JIT: never inline this method |
| Pragma | Meaning |
|---|---|
UninterruptiblePragma |
Older style: throw in method body to mark as uninterruptible |
InterruptiblePragma |
Override inherited uninterruptibility |
InlinePragma |
Older style: throw to hint inlining |
NoInlinePragma |
Older style: throw to prevent inlining |
NoOptCompilePragma |
Skip optimization passes for this method |
Prefer the @Annotation style over the pragma/exception style in new code.
These represent raw machine values that bypass the Java type system:
| Type | Represents |
|---|---|
Address |
Raw memory address (pointer) |
Offset |
Signed offset from an address |
Word |
Machine-word-sized unsigned integer |
Extent |
Unsigned size value |
ObjectReference |
Raw object pointer |
These are "unboxed" — they don't have object headers and can't be stored in Object variables. The JIT compiler handles them specially.
| Pattern | Usage |
|---|---|
Vm prefix |
VM-internal classes (VmThread, VmSystem, VmProcessor) |
Default prefix |
Standard implementations (DefaultPluginManager) |
*Model suffix |
XML-parsed descriptor models (PluginDescriptorModel) |
*Impl suffix |
Interface implementations (ResourceManagerImpl) |
*Plugin suffix |
Plugin entry point classes (DMAPlugin) |
// Use Unsafe.debug() for output — System.out may not be ready
Unsafe.debug("Error: something went wrong\n");// Use BootLogInstance for early boot, Logger after initialization
BootLogInstance.get().error("Error message", exception);- Empty catch blocks — Always at minimum log the exception
-
e.printStackTrace()— Use proper logging instead -
System.exit()— This halts the entire OS, not just your process
Services are registered via InitialNaming:
// Register
InitialNaming.bind(DeviceManager.NAME, deviceManager);
// Lookup
DeviceManager dm = InitialNaming.lookup(DeviceManager.NAME);This is JNode's equivalent of a service locator / JNDI.
When working with hardware resources (I/O ports, IRQ, DMA, memory-mapped I/O):
// Always claim resources through ResourceManager
ResourceManager rm = InitialNaming.lookup(ResourceManager.NAME);
IOResource io = rm.claimIOResource(owner, startPort, length);
try {
// use io
} finally {
io.release();
}public class MyPlugin extends Plugin {
protected void startPlugin() throws PluginException {
// Get extensions registered at our extension point
ExtensionPoint ep = getDescriptor().getExtensionPoint("my-point");
for (Extension ext : ep.getExtensions()) {
// Process each extension
}
}
}<extension point="org.jnode.driver.bus.pci.device-factories">
<device-factory class="com.example.MyDriver"/>
</extension>| Don't | Do Instead |
|---|---|
new String(str) |
Just use str directly |
str.length() == 0 |
str.isEmpty() |
new Integer(x) |
Integer.valueOf(x) |
catch (Exception e) {} |
At minimum log.error("...", e)
|
e.printStackTrace() |
Proper logging |
synchronized in driver hot path |
Use ProcessorLock or SpinLock
|
| Direct field access to VM internals | Use facade interfaces |
- VM-Magic — Deep dive into magic annotations
- Architecture — System structure
- Plugin-System — How to write plugins
- Build-System — Formatting, encoding requirements