import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@Component
public class JvmMonitor implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger logger = LoggerFactory.getLogger(JvmMonitor.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
int pid = getProcessID();
String[] cmds = new String[]{
"jps -lvm",
"jmap -heap " + pid,
"jmap -histo " + pid + " |head -20",
"jcmd " + pid + " GC.class_histogram | head -20",
"jstack " + pid
};
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("jvm-schedule-monitor");
return thread;
}
});
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
long freeMemory = Runtime.getRuntime().freeMemory();
long maxMemory = Runtime.getRuntime().maxMemory();
String printRatio = System.getProperty("jvm.print.memory.ratio");
if (StringUtils.isBlank(printRatio) || printRatio.matches("\\d+\\.\\d+")) {
printRatio = "0.2";
}
double jvmPrintRatio = Double.parseDouble(printRatio);
if (freeMemory < maxMemory * 0.2) {
monitorSystem(cmds);
}
}
}, 1, 10 * 60, TimeUnit.SECONDS);
}
public static void monitorSystem(String[] cmds) {
for (String cmd : cmds) {
try {
String result = execCmd(cmd);
logger.info("{}[root@60 ~]#{}{}{}", System.lineSeparator(), cmd, System.lineSeparator(), result);
} catch (IOException | InterruptedException e) {
logger.error("执行系统命令" + cmd + "报错:" + e.getMessage(), e);
}
}
}
private static String execCmd(String cmd) throws IOException, InterruptedException {
Process ps = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream(), StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
result.append(line).append(System.lineSeparator());
}
br.close();
ps.waitFor();
return result.toString();
}
private static int getProcessID() {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
return Integer.valueOf(runtimeMXBean.getName().split("@")[0]);
}
}
|