How to Understand Jenkins' Internal Architecture From the Code: A Developer's Guide
Jenkins is a modular, extensible Java application centered around the Jenkins singleton, which orchestrates subsystems including plugin management, extension points, job hierarchies, build execution, and security through specific classes like PluginManager, ExtensionList, and Queue.
To truly understand Jenkins' internal architecture from the code, you must explore the jenkinsci/jenkins repository, where the core Java modules reveal a design built on the Jenkins singleton as the global state coordinator. The architecture separates concerns into distinct subsystems—each with dedicated entry points in the source tree—that handle everything from plugin isolation to build scheduling via the Stapler web framework.
Core Engine and Global State
The heart of Jenkins resides in jenkins/model/Jenkins.java, where the Jenkins singleton class manages the application lifecycle. This class implements StaplerProxy to serve as the root object for the web UI and provides access to all major subsystems through methods like getPluginManager() and getQueue(). When the servlet container starts, hudson.WebAppMain instantiates this singleton, triggering the InitReactor (InitReactorRunner) to walk through initialization phases defined in hudson/init/InitMilestone.java, including PLUGINS_PREPARED and EXTENSIONS_AUGMENTED.
Plugin Management and Isolation
Plugin discovery and loading are handled by hudson/PluginManager.java (and its subclass LocalPluginManager), which maintains a map of PluginWrapper objects representing each installed plugin. Each plugin receives its own class loader (ExistanceCheckingClassLoader or CachingClassLoader), enabling hot-reloading and isolation. You can inspect loaded plugins programmatically:
Jenkins jenkins = Jenkins.get();
PluginManager pm = jenkins.getPluginManager();
for (PluginWrapper pw : pm.getPlugins()) {
System.out.println(pw.getShortName() + " – " + pw.getVersion());
}
Extension Mechanism
Jenkins uses an annotation-driven extension system defined in hudson/ExtensionList.java. Classes annotated with @Extension are discovered by ExtensionFinder during startup and registered in ExtensionList instances for each extension point. To retrieve all implementations of a specific type (such as SCM providers):
ExtensionList<SCM> scms = Jenkins.get().getExtensionList(SCM.class);
scms.forEach(scm -> System.out.println(scm.getClass().getName()));
Item and Job Hierarchy
The model layer, defined in hudson/model/Item.java and hudson/model/Job.java, represents all configurable entities. All top-level items implement TopLevelItem, while ItemGroup provides container semantics for hierarchical organization. The Job class extends this hierarchy to add build-related methods like getBuilds() and scheduleBuild().
Build Execution and Run Management
Builds are tracked through the Run class hierarchy in hudson/model/Run.java, with concrete implementations like Build for freestyle projects. The Executor class (referenced in hudson/model/Queue.java) runs build threads on agents, managing workspaces and result recording via WorkspaceCleanupThread.
Queue and Scheduling System
The hudson/model/Queue.java file contains the Queue class, which holds pending build requests as Queue.Item objects. When resources become available, the queue consults Computer instances (representing agents) and their Executor pools to assign tasks. Flyweight tasks (like pipeline steps) run on the master, while heavyweight tasks distribute to agents.
Security and Authorization
Security is managed through hudson/security/SecurityRealm.java, which defines authentication mechanisms (LDAP, Unix, etc.), and AuthorizationStrategy, which creates ACL objects governing permissions. Every Item and Run maintains an ACL checked via hasPermission(). CSRF protection is implemented through CrumbIssuer.
ACL acl = Jenkins.get().getAuthentication().impersonate(User.current());
System.out.println("Can read config? " + acl.hasPermission(Jenkins.READ));
Stapler Web Framework
Jenkins uses Stapler for URL routing and request handling, with integration points in hudson/web/StaplerProxy.java. The framework maps URLs to Java methods by convention, allowing Jenkins to serve as the URL root (/) while delegating to RootAction implementations for specific paths.
Configuration and Persistence
Configuration serialization uses XStream via hudson/util/XmlFile.java and XStream2. The PersistedList class handles collections that automatically save to disk, ensuring that changes to jobs or system configuration persist across restarts.
Practical Code Examples for Navigating the Architecture
Creating and Configuring Jobs Programmatically
To create a freestyle job through the API, use the createProject method in Jenkins.java:
Jenkins jenkins = Jenkins.get();
FreeStyleProject proj = jenkins.createProject(FreeStyleProject.class, "example-job");
proj.setDescription("Created via the Jenkins API");
proj.save();
Scheduling Builds and Inspecting Queue Status
Triggering a build returns a Queue.Item from hudson/model/Queue.java:
Job<?,?> job = Jenkins.get().getItemByFullName("example-job", Job.class);
Queue.Item queueItem = job.scheduleBuild2(0).getItem();
System.out.println("Queued: " + queueItem.getId());
Summary
- The
Jenkinssingleton (jenkins/model/Jenkins.java) serves as the central hub, managing global state and providing access to all subsystems. - Plugin isolation is enforced through dedicated class loaders managed by
PluginManager(hudson/PluginManager.java), withPluginWrappertracking metadata. - Extensions are discovered via the
@Extensionannotation and aggregated inExtensionList(hudson/ExtensionList.java) for dependency injection. - Job hierarchies are modeled through
ItemandJob(hudson/model/Item.java), withQueue(hudson/model/Queue.java) handling scheduling acrossComputeragents. - Security is enforced through
ACLobjects created bySecurityRealm(hudson/security/SecurityRealm.java) and checked on all sensitive operations. - Persistence relies on XStream serialization via
XmlFile(hudson/util/XmlFile.java), storing configuration as XML on disk.
Frequently Asked Questions
What is the best starting point for understanding Jenkins' internal architecture from the code?
Begin with jenkins/model/Jenkins.java, which contains the singleton instance and entry points to all major subsystems. This file shows how the PluginManager, Queue, and security components are wired together during initialization in hudson.WebAppMain.
How does Jenkins isolate plugins at runtime?
Each plugin loads in its own ExistanceCheckingClassLoader or CachingClassLoader, managed by hudson/PluginManager.java. This isolation prevents class conflicts between plugins while allowing the core to hot-reload or uninstall plugins safely via the PluginWrapper abstraction.
What is Stapler and how does it relate to Jenkins' architecture?
Stapler is the web framework that binds URLs to Java object methods by convention. Defined in hudson/web/StaplerProxy.java, it enables Jenkins to act as the URL root and routes HTTP requests to the appropriate Item, Run, or RootAction without explicit servlet mapping.
How does Jenkins decide which agent executes a build?
The Queue class (hudson/model/Queue.java) evaluates available Computer instances (agents) and their Executor pools, matching task requirements (labels, resources) against agent capabilities. Once matched, the Executor thread runs the build using the Run class to track execution state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →