This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/main by this push:
new 327ea0d85a Install the SIGHUP dump handler reflectively (#2852)
327ea0d85a is described below
commit 327ea0d85a36cf4b5b0cd888f0eeee870e632228
Author: Holger Friedrich <[email protected]>
AuthorDate: Wed Sep 9 07:43:55 2026 +0200
Install the SIGHUP dump handler reflectively (#2852)
* Install the SIGHUP dump handler reflectively
This avoids warnings during compilation which are printed in every CI
summary.
sun.misc.Signal and SignalHandler are internal proprietary APIs.
The approach is taken over from Main.java.
* Address review findings
---
.../karaf/diagnostic/core/internal/Activator.java | 14 ++---
.../diagnostic/core/internal/DumpHandler.java | 65 +++++++++++++++++-----
2 files changed, 56 insertions(+), 23 deletions(-)
diff --git
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
index 4b84bb750a..911d475954 100644
---
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
+++
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java
@@ -16,28 +16,24 @@
*/
package org.apache.karaf.diagnostic.core.internal;
-import java.io.Closeable;
-
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
- Closeable dumpHandler;
+ DumpHandler dumpHandler;
public void start(BundleContext context) throws Exception {
if (!isWindows()) {
- ClassLoader cl = this.getClass().getClassLoader();
try {
- Class<?> dumpHandlerClazz =
cl.loadClass("org.apache.karaf.diagnostic.core.internal.DumpHandler");
- dumpHandler = (Closeable)
dumpHandlerClazz.getConstructor(BundleContext.class).newInstance(context);
- } catch (Throwable e) {
- // Will happen if sun.misc.SignalHandler is not available
+ dumpHandler = new DumpHandler(context);
+ } catch (Exception | LinkageError e) {
+ // Will happen if sun.misc.Signal is not available or cannot
be initialized
}
}
}
public void stop(BundleContext context) throws Exception {
- if (dumpHandler != null && !isWindows()) {
+ if (dumpHandler != null) {
dumpHandler.close();
}
}
diff --git
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/DumpHandler.java
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/DumpHandler.java
index a70371c85b..34d454a192 100644
---
a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/DumpHandler.java
+++
b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/DumpHandler.java
@@ -19,6 +19,8 @@ package org.apache.karaf.diagnostic.core.internal;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -27,29 +29,64 @@ import org.apache.karaf.diagnostic.core.DumpDestination;
import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
import org.osgi.framework.BundleContext;
-import sun.misc.Signal;
-import sun.misc.SignalHandler;
+/**
+ * Creates a dump when the process receives SIGHUP. sun.misc.Signal is used
reflectively, as in
+ * org.apache.karaf.main.Main, to avoid the compiler warning about internal
proprietary API.
+ */
+public class DumpHandler implements Closeable {
-public class DumpHandler implements SignalHandler, Closeable {
private static final String SIGNAL = "HUP";
- private BundleContext context;
- private SignalHandler previous;
- public DumpHandler(BundleContext context) {
+ private final BundleContext context;
+ private final Method handleMethod;
+ private final Object signal;
+ private final Object previous;
+
+ public DumpHandler(BundleContext context) throws Exception {
this.context = context;
- previous = sun.misc.Signal.handle(new Signal(SIGNAL), this);
+
+ final Class<?> signalClass = Class.forName("sun.misc.Signal");
+ final Class<?> signalHandlerClass =
Class.forName("sun.misc.SignalHandler");
+
+ Object signalHandler =
Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class<?>[] {
+ signalHandlerClass
+ },
+ (proxy, method, args) -> {
+ if ("handle".equals(method.getName())) {
+ handle();
+ return null;
+ }
+ // Object methods such as equals, hashCode and toString
+ return method.invoke(this, args);
+ }
+ );
+
+ handleMethod = signalClass.getMethod("handle", signalClass,
signalHandlerClass);
+ signal = signalClass.getConstructor(String.class).newInstance(SIGNAL);
+ previous = handleMethod.invoke(null, signal, signalHandler);
}
-
- public void handle(Signal signal) {
- SimpleDateFormat dumpFormat = new
SimpleDateFormat("yyyy-MM-dd_HHmmss-SSS");
- String fileName = "dump-" + dumpFormat.format(new Date()) + ".zip";
- DumpDestination destination = new ZipDumpDestination(new
File(fileName));
- Dump.dump(context, destination, false, false);
+
+ /**
+ * Creates the dump on a short-lived thread, so that the JVM signal
dispatch thread is not
+ * blocked while everything is collected and zipped.
+ */
+ private void handle() {
+ new Thread(() -> {
+ SimpleDateFormat dumpFormat = new
SimpleDateFormat("yyyy-MM-dd_HHmmss-SSS");
+ String fileName = "dump-" + dumpFormat.format(new Date()) + ".zip";
+ DumpDestination destination = new ZipDumpDestination(new
File(fileName));
+ Dump.dump(context, destination, false, false);
+ }, "karaf-diagnostic-dump").start();
}
@Override
public void close() throws IOException {
- sun.misc.Signal.handle(new Signal(SIGNAL), previous);
+ try {
+ handleMethod.invoke(null, signal, previous);
+ } catch (Exception e) {
+ throw new IOException("Cannot restore the previous " + SIGNAL + "
handler", e);
+ }
}
}