Skip to main content
Paper plugins go through several distinct phases during their lifecycle. Understanding these phases is crucial for proper plugin initialization and cleanup.

Lifecycle Phases

The plugin lifecycle consists of three main phases, plus optional bootstrapping and loading phases:

Loader Phase (Optional)

The loader phase occurs before the plugin class is instantiated and runs in a separate classloader.

PluginLoader Interface

Implement io.papermc.paper.plugin.loader.PluginLoader to configure your plugin’s classpath:
Register in paper-plugin.yml:
Static values set in the loader class will not persist when the plugin loads due to different classloaders.

Bootstrap Phase (Optional)

The bootstrap phase runs before the server is fully loaded, allowing early initialization.

PluginBootstrap Interface

Implement io.papermc.paper.plugin.bootstrap.PluginBootstrap for early setup:
Register in paper-plugin.yml:
The bootstrap phase is experimental. Only call API methods explicitly documented to work during bootstrap. Most Bukkit API calls will throw exceptions or return null.

Custom Plugin Instantiation

You can override how your plugin is created:

Load Phase

The load phase occurs when your plugin is loaded but before it’s enabled.

onLoad() Method

Override the onLoad() method in your JavaPlugin class:
Use onLoad() for initialization that needs to happen before the server finishes starting up, such as registering world generators.

Load Order

Control when your plugin loads with the load field in paper-plugin.yml:
  • STARTUP - Loads during server startup, before worlds
  • POSTWORLD - Loads after worlds are loaded

Enable Phase

The enable phase is when your plugin becomes active and starts functioning.

onEnable() Method

This is the main entry point for your plugin:

Lifecycle Event Registration

During onEnable(), you can register lifecycle event handlers:
For Paper plugins (not legacy Bukkit plugins), you cannot use getCommand() during onEnable(). Use registerCommand() instead or register via lifecycle events.

Running Phase

Once enabled, your plugin is fully active and responds to events, commands, and scheduled tasks.

Checking if Enabled

You can check if your plugin is currently enabled:

Internal State

The JavaPlugin class tracks its state:
From JavaPlugin.java:272-288:

Disable Phase

The disable phase occurs when the plugin is being shut down.

onDisable() Method

Clean up resources when your plugin is disabled:
Always implement onDisable() to ensure proper cleanup. This prevents resource leaks and data loss.

Complete Lifecycle Example

Key Lifecycle Methods Summary

Best Practices

  1. Use the right phase: Don’t do heavy initialization in onLoad() that belongs in onEnable()
  2. Always implement onDisable(): Clean up resources to prevent memory leaks
  3. Don’t block the main thread: Keep lifecycle methods fast
  4. Handle errors gracefully: Catch exceptions in lifecycle methods to prevent plugin load failures
  5. Log lifecycle events: Help with debugging by logging what’s happening