pinpoint-apm/pinpoint · warning
Unknown ShutdownHookRegister
Error message
Unknown ShutdownHookRegister : {} What it means
WARN in ShutdownHookRegisterProvider.createShutdownHookRegister: the configured shutdown hook class was found via Class.forName but has no no-arg constructor (NoSuchMethodException), so the provider logs this and falls back to RUNTIME_SHUTDOWN_HOOK_REGISTER. The agent keeps running with the default runtime shutdown hook instead of the configured one.
Solutions
- Add a public no-argument constructor to the configured ShutdownHookRegister class.
- Verify the configured class name points to the intended implementation.
- Accept the RUNTIME_SHUTDOWN_HOOK_REGISTER fallback if a custom hook is not required.
Example fix
// before
public class MyShutdownHookRegister implements ShutdownHookRegister {
public MyShutdownHookRegister(String name) { ... }
}
// after
public class MyShutdownHookRegister implements ShutdownHookRegister {
public MyShutdownHookRegister() { }
public MyShutdownHookRegister(String name) { ... }
} Defensive patterns
Strategy: fallback
Validate before calling
Class<?> c = Class.forName(className);
if (!ShutdownHookRegister.class.isAssignableFrom(c) || c.getConstructor() == null) {
logger.warn("{} is not a usable ShutdownHookRegister (needs public no-arg ctor)", className);
} Type guard
boolean isUsableShutdownHookRegister(Class<?> c) {
try {
return ShutdownHookRegister.class.isAssignableFrom(c) && c.getConstructor() != null;
} catch (NoSuchMethodException e) {
return false;
}
} Try / catch
try {
return createCustomShutdownHookRegister(className);
} catch (ReflectiveOperationException | IllegalArgumentException e) {
logger.warn("Falling back to runtime shutdown hook register", e);
return RUNTIME_SHUTDOWN_HOOK_REGISTER;
} Prevention
- Always give custom ShutdownHookRegister classes a public no-argument constructor.
- Write a unit test that instantiates the configured class reflectively.
- Check agent logs at startup to confirm which shutdown hook register is active.
When it happens
Trigger: Setting the custom ShutdownHookRegister class name (profiler.shutdown.hook.register class config) to a class that lacks a public no-argument constructor.
Common situations: Custom ShutdownHookRegister implemented with only parameterized constructors; class changed API between versions; using a class from a different library that isn't a proper ShutdownHookRegister implementation.
Related errors
- access error
- injectField error field
- ModuleFactory initialize fail
- unsupported data type
- Unsupported type
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/afc1d6a4c5124002.
Report an issue: GitHub.
Appendix: source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/provider/ShutdownHookRegisterProvider.java:105
return JDK7_SHUTDOWN_HOOK_REGISTER;
}
return null;
}
private ShutdownHookRegister createShutdownHookRegister(String classToLoad) {
if (classToLoad == null) {
return RUNTIME_SHUTDOWN_HOOK_REGISTER;
}
try {
@SuppressWarnings("unchecked")
Class<ShutdownHookRegister> shutdownHookRegisterClass = (Class<ShutdownHookRegister>) Class.forName(classToLoad);
try {
Constructor<ShutdownHookRegister> shutdownHookRegisterConstructorConstructor = shutdownHookRegisterClass.getConstructor();
return shutdownHookRegisterConstructorConstructor.newInstance();
} catch (NoSuchMethodException e) {
logger.warn("Unknown ShutdownHookRegister : {}", classToLoad);
return RUNTIME_SHUTDOWN_HOOK_REGISTER;
}
} catch (ReflectiveOperationException e) {
logger.warn("Error creating ShutdownHookRegister [" + classToLoad + "]", e);
}
return RUNTIME_SHUTDOWN_HOOK_REGISTER;
}
private static class RuntimeShutdownHookRegister implements ShutdownHookRegister {
private final Logger logger = LogManager.getLogger(this.getClass());
@Override
public void register(Thread thread) {
Runtime.getRuntime().addShutdownHook(thread);
logger.info("register() completed. (ShutdownHook registered in java.lang.Runtime.)");
}
View on GitHub (pinned to 744c3d3075)