Skip to content

Application Entry Point and Initialization

Samera2022 edited this page Jan 30, 2026 · 1 revision

Application Entry Point and Initialization

Relevant source files

Purpose and Scope

This document describes the application bootstrap process in the MouseMacros system. The MouseMacro class serves as the application entry point, executing the minimal initialization sequence required before the main UI can launch. This includes configuring the JNativeHook native library path and delegating UI creation to the Swing Event Dispatch Thread (EDT).

Related Pages:

System Context

The MouseMacro entry point is the first code executed by the JVM and serves as the initialization coordinator for the entire application. From the high-level architecture (Diagram 1), the entry point's responsibilities are:

  1. Configure JNativeHook library system properties before any hooks are registered
  2. Launch the MainFrame singleton on the Swing EDT
  3. Enable the GlobalMouseListener to access native libraries through proper path configuration
flowchart TD

JVM["JVM"]
MouseMacro["MouseMacro.main()"]
ConfigManagerStatic["ConfigManager.CONFIG_DIR<br>(static field)"]
SystemProperties["System.setProperty()<br>jnativehook.lib.path"]
SwingUtilities["SwingUtilities.invokeLater()"]
MAIN_FRAME["MainFrame.MAIN_FRAME<br>(singleton)"]

JVM --> MouseMacro
MouseMacro --> ConfigManagerStatic
MouseMacro --> SystemProperties
MouseMacro --> SwingUtilities
SwingUtilities --> MAIN_FRAME
Loading

Diagram: Entry Point Position in Application Layer

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L1-L18

Main Class Structure

The MouseMacro class defines the application entry point through its main() method. This class has no instance methods, fields, or constructors—it exists solely to bootstrap the application.

Property Value
Package io.github.samera2022.mouse_macros
Class Name MouseMacro
Entry Method public static void main(String[] args)
Source File src/io/github/samera2022/mouse_macros/MouseMacro.java L9-L17

Import Dependencies

flowchart TD

MouseMacro["MouseMacro"]
SystemUtil["io.github.samera2022.mouse_macros.util.SystemUtil"]
SwingUtilities["javax.swing.SwingUtilities"]
MAIN_FRAME_Import["static import:<br>io.github.samera2022.mouse_macros.ui.frame.MainFrame.MAIN_FRAME"]
ConfigManager["io.github.samera2022.mouse_macros.manager.ConfigManager"]

MouseMacro --> SystemUtil
MouseMacro --> SwingUtilities
MouseMacro --> MAIN_FRAME_Import
MouseMacro --> ConfigManager
Loading

Diagram: MouseMacro Import Structure

The class imports:

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L1-L7

Bootstrap Sequence

The main() method executes a two-phase initialization sequence:

sequenceDiagram
  participant JVM
  participant MouseMacro["MouseMacro.main()"]
  participant ConfigManager["ConfigManager.CONFIG_DIR"]
  participant FileSystem["File System"]
  participant SystemProperties["System.setProperty()"]
  participant SwingUtilities["SwingUtilities"]
  participant EDT["Swing EDT"]
  participant MAIN_FRAME["MainFrame.MAIN_FRAME"]
  participant MouseMacro
  participant FileSystem
  participant ConfigManager
  participant SystemProperties
  participant MAIN_FRAME
  participant SwingUtilities
  participant EDT

  JVM->>MouseMacro: "invoke main()"
  note over MouseMacro,FileSystem: Phase 1: Native Library Configuration (Main Thread)
  MouseMacro->>MouseMacro: "dllName = 'JNativeHook.x86_64.dll'"
  MouseMacro->>ConfigManager: "access CONFIG_DIR"
  ConfigManager-->>MouseMacro: "config directory path"
  MouseMacro->>MouseMacro: "libDir = new File(configDir + '/libs/', dllName)"
  MouseMacro->>FileSystem: "libDir.exists()?"
  loop [Directory does not exist]
    FileSystem-->>MouseMacro: "false"
    MouseMacro->>FileSystem: "libDir.mkdirs()"
  end
  MouseMacro->>SystemProperties: "setProperty('jnativehook.lib.path', libDir.getAbsolutePath())"
  note over MouseMacro,MAIN_FRAME: Phase 2: UI Initialization (EDT)
  MouseMacro->>SwingUtilities: "invokeLater(() -> MAIN_FRAME.setVisible(true))"
  SwingUtilities->>EDT: "enqueue lambda"
  MouseMacro-->>JVM: "main() returns"
  EDT->>MAIN_FRAME: "setVisible(true)"
  note over MAIN_FRAME: Triggers MainFrame singleton initialization
Loading

Diagram: Complete Bootstrap Execution Flow

Phase 1: Native Library Configuration

Executed synchronously on the main thread src/io/github/samera2022/mouse_macros/MouseMacro.java L11-L15

This phase must complete before JNativeHook classes are loaded, otherwise the JVM will fail to find the native library.

Critical ordering: System property jnativehook.lib.path must be set before any code references org.jnativehook.* classes.

Phase 2: UI Thread Initialization

Executed asynchronously on the EDT src/io/github/samera2022/mouse_macros/MouseMacro.java L16

The main thread enqueues the UI initialization task and terminates. All subsequent application logic runs on the EDT or background threads spawned by application components.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L10-L16

Native Library Configuration

The first critical operation is configuring the JNativeHook native library path before any UI code executes.

Library Path Setup Logic

flowchart TD

start["main() execution"]
dllName["Line 11:<br>dllName = 'JNativeHook.x86_64.dll'"]
configDir["Line 12:<br>configDir = ConfigManager.CONFIG_DIR"]
libDir["Line 13:<br>libDir = new File(configDir+'/libs/', dllName)"]
existsCheck["Line 14:<br>libDir.exists()"]
mkdirs["libDir.mkdirs()"]
setProperty["Line 15:<br>System.setProperty('jnativehook.lib.path',<br>libDir.getAbsolutePath())"]

start --> dllName
start --> configDir
dllName --> libDir
configDir --> libDir
libDir --> existsCheck
existsCheck --> mkdirs
existsCheck --> setProperty
mkdirs --> setProperty
Loading

Diagram: JNativeHook Native Library Path Configuration

The native library setup executes these operations:

Line Operation Description
11 dllName = "JNativeHook.x86_64.dll" Hardcoded Windows x64 library name
12 configDir = ConfigManager.CONFIG_DIR Reads static field containing platform-specific config directory path
13 new File(configDir+"/libs/", dllName) Constructs path: {CONFIG_DIR}/libs/JNativeHook.x86_64.dll
14 if (!libDir.exists()) libDir.mkdirs() Creates directory structure if missing
15 System.setProperty("jnativehook.lib.path", ...) Configures JVM system property for native library loading

Important: The mkdirs() call creates both the libs/ directory and any missing parent directories. On first run, this ensures the entire directory structure exists.

Resulting File System Layout

After the first application launch, the directory structure is:

{CONFIG_DIR}/
├── config.cfg          (created by ConfigManager)
├── cache.json          (created by CacheManager)
└── libs/
    └── JNativeHook.x86_64.dll  (created by MouseMacro.main)

The libs/ directory and parent directories are created by mkdirs() at src/io/github/samera2022/mouse_macros/MouseMacro.java L14

JNativeHook will later extract and load the native DLL from this location when GlobalMouseListener registers hooks.

Platform-specific paths for CONFIG_DIR:

  • Windows: %LOCALAPPDATA%\MouseMacros\
  • macOS: ~/Library/Application Support/MouseMacros/
  • Linux: ~/.local/share/MouseMacros/

See File and Path Utilities for CONFIG_DIR resolution logic.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L11-L14

UI Thread Initialization

After native library configuration, the main thread delegates UI creation to the Swing Event Dispatch Thread (EDT) using SwingUtilities.invokeLater() src/io/github/samera2022/mouse_macros/MouseMacro.java L16

Thread Handoff Mechanism

flowchart TD

MainThread["Main Thread<br>(MouseMacro.main)"]
invokeLater["SwingUtilities.invokeLater()"]
lambda["Lambda:<br>() -> MAIN_FRAME.setVisible(true)"]
EDTQueue["EDT Event Queue"]
EDT["Event Dispatch Thread"]
setVisible["MAIN_FRAME.setVisible(true)"]
MainFrameInit["MainFrame singleton initialization"]
MainThreadEnd["Main thread terminates"]

MainThread --> invokeLater
invokeLater --> lambda
lambda --> EDTQueue
MainThread --> MainThreadEnd
EDTQueue --> EDT
EDT --> setVisible
setVisible --> MainFrameInit
Loading

Diagram: EDT Delegation via SwingUtilities.invokeLater()

Why EDT Delegation is Required

Swing components are not thread-safe. All Swing operations (component creation, modification, event handling) must execute on a single thread: the EDT. Using SwingUtilities.invokeLater() ensures that:

  1. UI initialization happens on the EDT
  2. The main thread can terminate without blocking UI operations
  3. Thread safety constraints are satisfied

MAIN_FRAME Singleton Access

The MAIN_FRAME constant is statically imported src/io/github/samera2022/mouse_macros/MouseMacro.java L7

:

import static io.github.samera2022.mouse_macros.ui.frame.MainFrame.MAIN_FRAME;

MAIN_FRAME is a public static final MainFrame field defined in the MainFrame class. When the lambda executes MAIN_FRAME.setVisible(true), it triggers:

  1. Class Loading: The MainFrame class is loaded by the JVM classloader
  2. Static Initialization: The MAIN_FRAME singleton is constructed
  3. Constructor Execution: Complete UI initialization occurs (see Main Window (MainFrame)))
  4. Window Display: setVisible(true) displays the initialized window

The entire application UI is initialized lazily when MAIN_FRAME is first accessed.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L7-L16

Critical Ordering Constraints

The bootstrap sequence has strict ordering requirements to prevent runtime failures:

Order Operation Thread Line Constraint
1 Set jnativehook.lib.path system property Main 15 Must execute before JNativeHook classes are loaded
2 Enqueue UI initialization lambda Main 16 Must execute after library path configuration
3 Execute MAIN_FRAME.setVisible(true) EDT 16 Must execute on EDT (Swing threading requirement)

Why Order Matters

Native Library Loading: JNativeHook uses JNI (Java Native Interface) to load platform-specific DLLs. The JVM reads the jnativehook.lib.path system property when loading native code. If this property is not set before JNativeHook classes are accessed, the JVM will throw UnsatisfiedLinkError.

EDT Threading: Swing enforces single-threaded access to UI components. Calling setVisible() from the main thread would violate this constraint and could cause race conditions or deadlocks.

Dependency Chain

flowchart TD

JVM["JVM classloader"]
main["MouseMacro.main(args)<br>Line 10"]
configDir["ConfigManager.CONFIG_DIR<br>Line 12"]
libDirConstruct["new File(...)<br>Line 13"]
mkdirs["libDir.mkdirs()<br>Line 14"]
setProperty["System.setProperty()<br>Line 15"]
invokeLater["SwingUtilities.invokeLater()<br>Line 16"]
EDT["EDT execution"]
setVisible["MAIN_FRAME.setVisible(true)"]
MainFrameClassLoad["MainFrame class load"]
MainFrameSingleton["MAIN_FRAME field initialization"]

JVM --> main
main --> configDir
main --> libDirConstruct
libDirConstruct --> mkdirs
mkdirs --> setProperty
setProperty --> invokeLater
invokeLater --> EDT
EDT --> setVisible
setVisible --> MainFrameClassLoad
MainFrameClassLoad --> MainFrameSingleton
Loading

Diagram: Complete Method Invocation and Dependency Chain

The entry point performs minimal work—only 7 lines of executable code—before transferring control to MainFrame. This design keeps the bootstrap logic simple and focused.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L10-L16

Command-Line Arguments

The main() method signature includes the standard String[] args parameter src/io/github/samera2022/mouse_macros/MouseMacro.java L10

but this parameter is currently unused. The application does not support any command-line arguments.

All configuration is performed through:

Future Extension Point

If command-line argument parsing is added in the future, it should be inserted between lines 15 and 16:

System.setProperty("jnativehook.lib.path", libDir.getAbsolutePath());
// INSERT: parseCommandLineArgs(args) here
SwingUtilities.invokeLater(() -> MAIN_FRAME.setVisible(true));

This ensures arguments are processed after native library setup but before UI initialization.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L10

Error Handling

The main() method does not implement explicit error handling. All exceptions propagate to the JVM's default uncaught exception handler, which prints a stack trace to stderr and terminates the process.

Potential Failure Modes

Operation Line Failure Scenario Exception Type Recovery
ConfigManager.CONFIG_DIR access 12 Static initialization failure Various None - application cannot start
new File(...) 13 Invalid path characters None thrown Constructor succeeds with invalid path
libDir.mkdirs() 14 Insufficient permissions None thrown Returns false, continues execution
System.setProperty(...) 15 Security manager denies access SecurityException JVM terminates
SwingUtilities.invokeLater(...) 16 Null lambda (impossible here) NullPointerException JVM terminates
MAIN_FRAME initialization 16 (EDT) UI construction failure Various (e.g., HeadlessException) EDT exception handler logs and terminates

No Graceful Degradation

The application does not attempt graceful degradation on initialization failure. If the bootstrap sequence fails:

  1. The exception propagates to the JVM
  2. The JVM prints the stack trace
  3. The process terminates with non-zero exit code

Design Rationale: Bootstrap failures indicate severe environmental issues (missing directories, security restrictions, headless environment). Recovery is not practical, and early termination prevents the application from running in an invalid state.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L10-L16

Platform Support

Current Implementation: Windows x64 Only

The native library name is hardcoded as "JNativeHook.x86_64.dll" src/io/github/samera2022/mouse_macros/MouseMacro.java L11

which restricts the application to 64-bit Windows systems. The application will fail to start on other platforms because:

  1. JNativeHook cannot find the appropriately-named library file
  2. The Windows DLL format is incompatible with Linux/macOS

Multi-Platform Support Requirements

To support additional platforms, the entry point would need OS and architecture detection logic:

String osName = System.getProperty("os.name").toLowerCase();
String osArch = System.getProperty("os.arch").toLowerCase();

String dllName;
if (osName.contains("win")) {
    dllName = "JNativeHook.x86_64.dll";
} else if (osName.contains("mac")) {
    dllName = "libJNativeHook.x86_64.dylib";
} else if (osName.contains("nux")) {
    dllName = "libJNativeHook.x86_64.so";
}

Required library files per platform:

Platform Architecture Library File Name Extension
Windows x86_64 JNativeHook.x86_64.dll Windows PE DLL
Linux x86_64 libJNativeHook.x86_64.so ELF Shared Object
macOS x86_64 libJNativeHook.x86_64.dylib Mach-O Dynamic Library
macOS ARM64 (M1/M2) libJNativeHook.arm64.dylib Mach-O Dynamic Library

Note: SystemUtil is imported src/io/github/samera2022/mouse_macros/MouseMacro.java L3

but unused. This utility class could provide platform detection helpers for future multi-platform support.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L3-L11

Integration Points

The MouseMacro entry point integrates with:

  1. ConfigManager: Retrieves CONFIG_DIR for library path construction src/io/github/samera2022/mouse_macros/MouseMacro.java L10
  2. MainFrame: Accesses singleton MAIN_FRAME instance src/io/github/samera2022/mouse_macros/MouseMacro.java L15
  3. JVM System Properties: Sets jnativehook.lib.path src/io/github/samera2022/mouse_macros/MouseMacro.java L13
  4. Swing EDT: Delegates UI work via SwingUtilities.invokeLater() src/io/github/samera2022/mouse_macros/MouseMacro.java L15
flowchart TD

MouseMacro["MouseMacro.main()"]
ConfigManager["ConfigManager"]
MainFrame["MainFrame.MAIN_FRAME"]
SystemProps["System Properties"]
SwingEDT["Swing EDT"]

MouseMacro --> ConfigManager
MouseMacro --> SystemProps
MouseMacro --> SwingEDT
SwingEDT --> MainFrame
Loading

Diagram: Entry Point Dependencies

After the entry point completes, control flow passes entirely to the Event Dispatch Thread and the event-driven Swing framework. The main thread terminates after enqueueing the UI initialization task.

Sources: src/io/github/samera2022/mouse_macros/MouseMacro.java L8-L16

Clone this wiki locally