37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/top4j-javaagent/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/top4j-javaagent/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/top4j-javaagent/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | io.top4j
6 | top4j-parent
7 | 1.1.2-SNAPSHOT
8 |
9 |
10 | top4j-javaagent
11 | jar
12 |
13 | Top4J JavaAgent
14 |
15 | Top4J is a lightweight, low overhead, production-ready performance analysis tool for the Java runtime environment.
16 |
17 | https://github.com/OpenAnswers/top4j
18 |
19 |
20 | UTF-8
21 |
22 |
23 |
24 |
25 |
26 | org.apache.maven.plugins
27 | maven-jar-plugin
28 | 3.3.0
29 |
30 |
31 |
32 | io.top4j.javaagent.controller.Agent
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/top4j-javaagent/sonar-project.properties:
--------------------------------------------------------------------------------
1 | # must be unique in a given SonarQube instance
2 | sonar.projectKey=top4j-javaagent
3 | # this is the name displayed in the SonarQube UI
4 | sonar.projectName=Top4J Java Agent
5 | sonar.projectVersion=0.0.1-SNAPSHOT
6 |
7 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
8 | # Since SonarQube 4.2, this property is optional if sonar.modules is set.
9 | # If not set, SonarQube starts looking for source code from the directory containing
10 | # the sonar-project.properties file.
11 | sonar.sources=.
12 |
13 | # Encoding of the source code. Default is default system encoding
14 | #sonar.sourceEncoding=UTF-8
15 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/config/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.config;
18 |
19 | public final class Constants {
20 |
21 | // JMX MXBean domain name
22 | public static final String DOMAIN = "io.top4j";
23 |
24 | // JMX MXBean JVM stats type
25 | public static final String JVM_STATS_TYPE = "JVM";
26 |
27 | // JMX MXBean top thread stats type
28 | public static final String TOP_THREAD_STATS_TYPE = "TopThread";
29 |
30 | // JMX MXBean blocked thread stats type
31 | public static final String BLOCKED_THREAD_STATS_TYPE = "BlockedThread";
32 |
33 | // JMX MXBean hot method stats type
34 | public static final String HOT_METHOD_STATS_TYPE = "HotMethod";
35 |
36 | // JMX MXBean threads stats type
37 | public static final String THREADS_STATS_TYPE = "ThreadStats";
38 |
39 | // JMX MXBean memory stats type
40 | public static final String MEMORY_STATS_TYPE = "MemoryStats";
41 |
42 | // JMX MXBean heap stats type
43 | public static final String HEAP_STATS_TYPE = "HeapStats";
44 |
45 | // JMX MXBean GC stats type
46 | public static final String GC_STATS_TYPE = "GCStats";
47 |
48 | // JMX MXBean agent type
49 | public static final String AGENT_TYPE = "Agent";
50 |
51 | // JMX MXBean agent stats type
52 | public static final String AGENT_STATS_TYPE = "AgentStats";
53 |
54 | // JMX MXBean stats logger type
55 | public static final String STATS_LOGGER_TYPE = "StatsLogger";
56 |
57 | // file path separator
58 | public static final String FILE_SEPARATOR = System.getProperty("file.separator");
59 |
60 | // default properties file name
61 | public static final String DEFAULT_PROPERTIES_FILE_NAME = "default-top4j.properties";
62 |
63 | // properties file name
64 | public static final String PROPERTIES_FILE_NAME = "top4j.properties";
65 |
66 | // test properties file name
67 | public static final String TEST_PROPERTIES_FILE_NAME = "top4j-test.properties";
68 |
69 | // properties file name argument token (used to specify properties file location via agent argument)
70 | public static final String PROPERTIES_FILE_NAME_ARG = "config.file";
71 |
72 | // 1 Mega Byte
73 | public static final int ONE_MEGA_BYTE = 1048576;
74 |
75 | private Constants() {
76 | throw new AssertionError();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/controller/Agent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.controller;
18 |
19 | import java.lang.instrument.Instrumentation;
20 | import java.lang.management.ManagementFactory;
21 | import java.util.logging.*;
22 |
23 | import io.top4j.javaagent.config.Configurator;
24 |
25 | import javax.management.MBeanServer;
26 |
27 | public class Agent {
28 |
29 | private static final Logger LOGGER = Logger.getLogger(Agent.class.getName());
30 |
31 | public static void premain(String agentArgs, Instrumentation inst) {
32 |
33 | // get platform MBean server
34 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
35 |
36 | // initialise configurator
37 | Configurator config = new Configurator(mbs, agentArgs);
38 |
39 | // create and start controller thread
40 | Controller controller = new Controller(config);
41 | controller.start();
42 |
43 | LOGGER.info("Top4J: Java agent activated.");
44 |
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/controller/Collector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.controller;
18 |
19 | import java.lang.management.ManagementFactory;
20 | import java.util.TimerTask;
21 |
22 | import javax.management.JMX;
23 | import javax.management.MBeanServer;
24 | import javax.management.MalformedObjectNameException;
25 | import javax.management.ObjectName;
26 |
27 | import io.top4j.javaagent.config.Configurator;
28 | import io.top4j.javaagent.config.Constants;
29 | import io.top4j.javaagent.exception.MBeanAccessException;
30 | import io.top4j.javaagent.mbeans.jvm.JVMStatsMXBean;
31 |
32 | public class Collector extends TimerTask {
33 |
34 | private JVMStatsMXBean jvmStats;
35 | private boolean statsLoggerEnabled;
36 |
37 | public Collector(Configurator config) throws MBeanAccessException {
38 |
39 | this.statsLoggerEnabled = config.isStatsLoggerEnabled();
40 |
41 | // create JVMStats objectName
42 | try {
43 | ObjectName jvmStatsObjectName = new ObjectName(Constants.DOMAIN + ":type=" + Constants.AGENT_TYPE + ",statsType=" + Constants.JVM_STATS_TYPE);
44 |
45 | // instantiate new JVMStatsMXBean proxy based on jvmStatsObjectName
46 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
47 |
48 | this.jvmStats = JMX.newMBeanProxy(mbs, jvmStatsObjectName, JVMStatsMXBean.class);
49 |
50 | } catch (MalformedObjectNameException e) {
51 | throw new MBeanAccessException(e, "JMX MalformedObjectNameException: " + e.getMessage());
52 | }
53 |
54 | }
55 |
56 | @Override
57 | public void run() {
58 |
59 | // update stats
60 | updateStats();
61 | if (statsLoggerEnabled) {
62 | // log stats
63 | logStats();
64 | }
65 |
66 | }
67 |
68 | private void logStats() {
69 |
70 | // log JVM stats
71 | jvmStats.log();
72 |
73 | }
74 |
75 | private void updateStats() {
76 |
77 | // update JVM stats
78 | jvmStats.update();
79 |
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/controller/Controller.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.controller;
18 |
19 | import java.util.Timer;
20 | import java.util.TimerTask;
21 | import java.util.logging.Logger;
22 |
23 | import io.top4j.javaagent.config.Configurator;
24 | import io.top4j.javaagent.config.Constants;
25 | import io.top4j.javaagent.mbeans.jvm.JVMStats;
26 | import io.top4j.javaagent.messaging.LoggerQueue;
27 | import io.top4j.javaagent.utils.MBeanHelper;
28 |
29 | import javax.management.MBeanServer;
30 |
31 | public final class Controller extends Thread {
32 |
33 | private LoggerQueue loggerQueue;
34 | private Configurator config;
35 | private long interval;
36 | private boolean statsLoggerEnabled;
37 |
38 | private static final Logger LOGGER = Logger.getLogger(LoggerThread.class.getName());
39 |
40 | /**
41 | * Create a polling thread to track JVM stats.
42 | * @param config the Top4J JavaAgent configuration
43 | */
44 | public Controller(Configurator config) {
45 | super("Top4J Monitor");
46 | this.config = config;
47 | this.interval = Long.parseLong(config.get("collector.poll.frequency"));
48 | this.statsLoggerEnabled = config.isStatsLoggerEnabled();
49 | if (statsLoggerEnabled) {
50 | // create LoggerQueue
51 | this.loggerQueue = new LoggerQueue(100);
52 | }
53 |
54 | try {
55 | // instantiate new MBeanHelper used to access JVMStats MBean attributes and operations
56 | MBeanHelper jvmStatsMBeanHelper = new MBeanHelper(Constants.AGENT_TYPE, Constants.JVM_STATS_TYPE);
57 | // instantiate new JVMStats MBean
58 | JVMStats jvmStatsMBean = new JVMStats(config, loggerQueue);
59 | // register JVMStats MBean with MBean server
60 | jvmStatsMBeanHelper.registerMBean(jvmStatsMBean);
61 |
62 | } catch (Exception e) {
63 | LOGGER.severe("Failed to initialise JVM stats MBean due to " + e.getMessage());
64 | }
65 |
66 | setDaemon(true);
67 | }
68 |
69 | /**
70 | * Run the thread until interrupted.
71 | */
72 | @Override
73 | public void run() {
74 |
75 | if (statsLoggerEnabled) {
76 | try {
77 | // create and start logger thread
78 | LoggerThread statsLogger = new LoggerThread(config, loggerQueue);
79 | statsLogger.start();
80 | } catch (Exception e) {
81 | LOGGER.severe("Failed to initialise LoggerThread due to " + e.getMessage());
82 | }
83 | }
84 |
85 | try {
86 | // create new TimerTask to run JVM stats collector
87 | TimerTask collector = new Collector(config);
88 | // create new Timer to schedule JVM stats collector
89 | Timer timer = new Timer("Top4J Stats Collector", true);
90 | // run JVM stats collector at fixed interval
91 | timer.scheduleAtFixedRate(collector, 0, interval);
92 | } catch (Exception e) {
93 | LOGGER.severe("Failed to initialise stats Collector thread due to " + e.getMessage());
94 | }
95 |
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/controller/LoggerThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.controller;
18 |
19 | import io.top4j.javaagent.config.Configurator;
20 | import io.top4j.javaagent.config.Constants;
21 | import io.top4j.javaagent.exception.MBeanAccessException;
22 | import io.top4j.javaagent.mbeans.logger.StatsLoggerMXBean;
23 | import io.top4j.javaagent.messaging.LoggerQueue;
24 |
25 | import javax.management.JMX;
26 | import javax.management.MBeanServer;
27 | import javax.management.MalformedObjectNameException;
28 | import javax.management.ObjectName;
29 | import java.lang.management.ManagementFactory;
30 | import java.util.logging.Logger;
31 |
32 | public class LoggerThread extends Thread {
33 |
34 | private LoggerQueue loggerQueue;
35 | private long interval;
36 | private boolean statsLoggerEnabled;
37 | private StatsLoggerMXBean statsLogger;
38 |
39 | private static final Logger LOGGER = Logger.getLogger(LoggerThread.class.getName());
40 |
41 | public LoggerThread(Configurator config, LoggerQueue loggerQueue) throws Exception {
42 |
43 | super("Top4J Stats LoggerThread");
44 | LOGGER.fine("Initialising Top4J Stats LoggerThread....");
45 | this.loggerQueue = loggerQueue;
46 | this.interval = Long.parseLong(config.get("stats.logger.poll.timeout"));
47 | this.statsLoggerEnabled = config.isStatsLoggerEnabled();
48 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
49 | // create StatsLogger objectName
50 | ObjectName statsLoggerObjectName = null;
51 | try {
52 | statsLoggerObjectName = new ObjectName(Constants.DOMAIN + ":" + "type=" + Constants.AGENT_TYPE + ",statsType=" + Constants.STATS_LOGGER_TYPE);
53 | } catch (MalformedObjectNameException e) {
54 | throw new MBeanAccessException(e, "JMX MalformedObjectNameException: " + e.getMessage());
55 | }
56 | // instantiate new statsLoggerMXBean proxy based on statsLoggerObjectName
57 | this.statsLogger = JMX.newMBeanProxy(mbs, statsLoggerObjectName, StatsLoggerMXBean.class);
58 | setDaemon(true);
59 | }
60 |
61 | /**
62 | * Run the thread until interrupted.
63 | */
64 | @Override
65 | public void run() {
66 | while (!isInterrupted()) {
67 | // poll loggerQueue for log stats notification
68 | String notification = loggerQueue.poll(interval);
69 | if (notification != null && statsLoggerEnabled) {
70 | // log JVM stats
71 | statsLogger.update();
72 | }
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/exception/MBeanAccessException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.exception;
18 |
19 | import javax.management.MBeanException;
20 |
21 | public class MBeanAccessException extends MBeanException {
22 |
23 | private static final long serialVersionUID = 1L;
24 |
25 | public MBeanAccessException(Exception e) {
26 | super(e);
27 | }
28 |
29 | public MBeanAccessException(Exception e, String message) {
30 | super(e, message);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/exception/MBeanDiscoveryException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.exception;
18 |
19 | public class MBeanDiscoveryException extends IllegalStateException {
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | public MBeanDiscoveryException(String message) {
24 | super(message);
25 | }
26 |
27 | public MBeanDiscoveryException(String message, Throwable cause) {
28 | super(message, cause);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/exception/MBeanInitException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.exception;
18 |
19 | import javax.management.MBeanRegistrationException;
20 |
21 | public class MBeanInitException extends MBeanRegistrationException {
22 |
23 | private static final long serialVersionUID = 1L;
24 |
25 | public MBeanInitException(Exception e) {
26 | super(e);
27 | }
28 |
29 | public MBeanInitException(Exception e, String message) {
30 | super(e, message);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/exception/MBeanRuntimeException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.exception;
18 |
19 | import javax.management.MBeanException;
20 |
21 | public class MBeanRuntimeException extends MBeanException {
22 |
23 | private static final long serialVersionUID = 1L;
24 |
25 | public MBeanRuntimeException(Exception e) {
26 | super(e);
27 | }
28 |
29 | public MBeanRuntimeException(Exception e, String message) {
30 | super(e, message);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/listener/CollectionListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.listener;
18 |
19 | import java.lang.management.MemoryNotificationInfo;
20 | import java.util.logging.Logger;
21 |
22 | import javax.management.MBeanServerConnection;
23 | import javax.management.Notification;
24 | import javax.management.openmbean.CompositeData;
25 |
26 | import io.top4j.javaagent.exception.MBeanInitException;
27 | import io.top4j.javaagent.mbeans.jvm.gc.GarbageCollectorMXBeanHelper;
28 | import io.top4j.javaagent.mbeans.jvm.memory.MemoryPoolMXBeanHelper;
29 | import io.top4j.javaagent.mbeans.jvm.memory.MemoryPoolUsageTracker;
30 |
31 | public class CollectionListener implements javax.management.NotificationListener {
32 |
33 | private GarbageCollectorMXBeanHelper gcMXBeanHelper;
34 | private MemoryPoolUsageTracker nurseryPoolUsageTracker;
35 | private MemoryPoolUsageTracker survivorPoolUsageTracker;
36 | private MemoryPoolUsageTracker tenuredPoolUsageTracker;
37 | private String survivorPoolName;
38 | private String tenuredPoolName;
39 |
40 | private static final Logger LOGGER = Logger.getLogger(CollectionListener.class.getName());
41 |
42 | public CollectionListener(MBeanServerConnection mbsc,
43 | MemoryPoolUsageTracker nurseryPoolUsageTracker,
44 | MemoryPoolUsageTracker survivorPoolUsageTracker,
45 | MemoryPoolUsageTracker tenuredPoolUsageTracker) throws Exception {
46 |
47 | this.nurseryPoolUsageTracker = nurseryPoolUsageTracker;
48 | this.survivorPoolUsageTracker = survivorPoolUsageTracker;
49 | this.tenuredPoolUsageTracker = tenuredPoolUsageTracker;
50 |
51 | // instantiate new MemoryPoolMXBeanHelper
52 | MemoryPoolMXBeanHelper memoryPoolMxBeanHelper = new MemoryPoolMXBeanHelper(mbsc);
53 |
54 | // instantiate new GarbageCollectorMXBeanHelper
55 | try {
56 | this.gcMXBeanHelper = new GarbageCollectorMXBeanHelper(mbsc);
57 | } catch (Exception e) {
58 | throw new MBeanInitException(e, "Failed to initialise Collection Listener due to: " + e.getMessage());
59 | }
60 |
61 | // get survivor pool name
62 | this.survivorPoolName = memoryPoolMxBeanHelper.getSurvivorSpacePoolName();
63 |
64 | // get tenured pool name
65 | this.tenuredPoolName = memoryPoolMxBeanHelper.getTenuredPoolName();
66 |
67 | }
68 |
69 | @Override
70 | public void handleNotification(Notification notification, Object handback) {
71 |
72 | String notifType = notification.getType();
73 | if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED) ||
74 | notifType.equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
75 | LOGGER.finer("MEMORY_THRESHOLD_EXCEEDED");
76 |
77 | // retrieve the memory notification information
78 | CompositeData cd = (CompositeData) notification.getUserData();
79 | MemoryNotificationInfo info = MemoryNotificationInfo.from(cd);
80 | String poolName = info.getPoolName();
81 |
82 | if (poolName.equals(survivorPoolName)) {
83 |
84 | try {
85 | LOGGER.finer("Collection Listener Nursery GC Count = " + gcMXBeanHelper.getNurseryGCCount());
86 | } catch (Exception e) {
87 | LOGGER.fine("Unable to retrieve Nursery GC Count");
88 | }
89 | // update nursery pool usage tracker
90 | nurseryPoolUsageTracker.update();
91 | LOGGER.finer("Collection Listener Nursery Pool Usage = " + nurseryPoolUsageTracker.getMemoryPoolIntervalUsage());
92 |
93 | try {
94 | LOGGER.finer("Collection Listener Survivor GC Count = " + gcMXBeanHelper.getNurseryGCCount());
95 | } catch (Exception e) {
96 | LOGGER.fine("Unable to retrieve Survivor GC Count");
97 | }
98 | // update survivor pool usage tracker
99 | survivorPoolUsageTracker.update();
100 | LOGGER.finer("Collection Listener Survivor Pool Usage = " + survivorPoolUsageTracker.getMemoryPoolIntervalUsage());
101 |
102 | }
103 |
104 | if (poolName.equals(tenuredPoolName)) {
105 |
106 | try {
107 | LOGGER.finer("Collection Listener Tenured GC Count = " + gcMXBeanHelper.getTenuredGCCount());
108 | } catch (Exception e) {
109 | LOGGER.fine("Unable to retrieve Tenured GC Count");
110 | }
111 | // update tenured pool usage tracker
112 | tenuredPoolUsageTracker.update();
113 | LOGGER.finer("Tenured Pool Usage = " + tenuredPoolUsageTracker.getMemoryPoolIntervalUsage());
114 |
115 | }
116 |
117 | }
118 |
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/StatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans;
18 |
19 | /**
20 | * Base stats MBean used to define MBean attributes and operations common to all Top4J MBeans.
21 | */
22 | public interface StatsMXBean {
23 |
24 | /**
25 | ** Update MBean attributes with latest data.
26 | */
27 | void update();
28 |
29 | /**
30 | * Sets the amount of CPU time in milliseconds consumed by the MBean update() operation per invocation.
31 | * @param mBeanCpuTime the amount of CPU time in milliseconds
32 | */
33 | void setMBeanCpuTime(double mBeanCpuTime);
34 |
35 | /**
36 | * Returns the amount of CPU time in milliseconds consumed by the MBean update() operation per invocation.
37 | * @return the amount of CPU time in milliseconds
38 | */
39 | double getMBeanCpuTime();
40 |
41 | /**
42 | * Sets whether the MBean is enabled (true) or disabled (false).
43 | *
44 | * Disabled MBeans will no longer receive updates via the MBean update() operation or the Top4J Java Agent stats update process.
45 | * An MBean will be marked as disabled if the update() operation encounters an unexpected exception.
46 | * @param enabled whether the MBean is enabled (true) or disabled (false).
47 | */
48 | void setEnabled(boolean enabled);
49 |
50 | /**
51 | * Returns whether the MBean is enabled (true) or disabled (false).
52 | *
53 | * Disabled MBeans will no longer receive updates via the MBean update() operation or the Top4J Java Agent stats update process.
54 | * @return whether the MBean is enabled (true) or disabled (false)
55 | */
56 | boolean getEnabled();
57 |
58 | /**
59 | * Sets the MBean failure reason.
60 | * If the update() operation encounters an unexpected exception the failure reason will be stored within the FailureReason MBean attribute.
61 | * @param failureReason the failure reason
62 | */
63 | void setFailureReason(String failureReason);
64 |
65 | /**
66 | * Returns the MBean failure reason.
67 | * If the update() operation encounters an unexpected exception the failure reason will be stored within the FailureReason MBean attribute.
68 | * @return the failure reason
69 | */
70 | String getFailureReason();
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/agent/AgentMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.agent;
18 |
19 | public interface AgentMXBean {
20 |
21 | void stop();
22 |
23 | void start();
24 |
25 | String setStatus(String status);
26 |
27 | String getStatus();
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/agent/AgentStatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.agent;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | /**
22 | * Used to store and expose stats relating to the Top4J JavaAgent run-time.
23 | */
24 |
25 | public interface AgentStatsMXBean extends StatsMXBean {
26 |
27 | /**
28 | * Sets the amount of CPU time in milliseconds consumed by all MBean update() operations per invocation.
29 | * @param cpuTime CPU time in milliseconds
30 | */
31 | void setAgentCpuTime(double cpuTime);
32 |
33 | /**
34 | * Returns the amount of CPU time in milliseconds consumed by all MBean update() operations per invocation.
35 | * @return the CPU time in milliseconds
36 | */
37 | double getAgentCpuTime();
38 |
39 | /**
40 | * Sets the percentage CPU utilisation of the Top4J JavaAgent background threads.
41 | * @param cpuUtil CPU utilisation as a percentage of wall clock time
42 | */
43 | void setAgentCpuUtil(double cpuUtil);
44 |
45 | /**
46 | * Returns the percentage CPU utilisation of the Top4J JavaAgent background threads.
47 | * @return CPU utilisation as a percentage of wall clock time
48 | */
49 | double getAgentCpuUtil();
50 |
51 | /**
52 | * Sets the number of Top4J JavaAgent stats update iterations since the JavaAgent was enabled.
53 | * @param iterations the number of iterations
54 | */
55 | void setIterations(long iterations);
56 |
57 | /**
58 | * Returns the number of Top4J JavaAgent stats update iterations since the JavaAgent was enabled.
59 | * @return the number of iterations
60 | */
61 | long getIterations();
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/JVMStatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | public interface JVMStatsMXBean extends StatsMXBean {
22 |
23 | void log();
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/CollectionUsageListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import java.lang.management.MemoryNotificationInfo;
20 | import java.util.logging.Logger;
21 |
22 | import javax.management.MBeanServerConnection;
23 | import javax.management.Notification;
24 |
25 | import io.top4j.javaagent.exception.MBeanInitException;
26 | import io.top4j.javaagent.mbeans.jvm.memory.MemoryPoolMXBeanHelper;
27 | import io.top4j.javaagent.mbeans.jvm.memory.MemorySurvivorBean;
28 |
29 | public class CollectionUsageListener implements javax.management.NotificationListener {
30 |
31 | private MemoryPoolMXBeanHelper memoryPoolMxBeanHelper;
32 | private GarbageCollectorMXBeanHelper gcMXBeanHelper;
33 | private MemorySurvivorBean memorySurvivor;
34 |
35 | private static final Logger LOGGER = Logger.getLogger(CollectionUsageListener.class.getName());
36 |
37 | public CollectionUsageListener(MBeanServerConnection mbsc, MemorySurvivorBean memorySurvivor) throws Exception {
38 |
39 | this.memorySurvivor = memorySurvivor;
40 |
41 | // instantiate new MemoryPoolMXBeanHelper
42 | try {
43 | this.memoryPoolMxBeanHelper = new MemoryPoolMXBeanHelper(mbsc);
44 | } catch (Exception e) {
45 | throw new MBeanInitException(e, "Failed to initialise Collection Usage Listener due to: " + e.getMessage());
46 | }
47 |
48 | // instantiate new GarbageCollectorMXBeanHelper
49 | try {
50 | this.gcMXBeanHelper = new GarbageCollectorMXBeanHelper(mbsc);
51 | } catch (Exception e) {
52 | throw new MBeanInitException(e, "Failed to initialise Collection Usage Listener due to: " + e.getMessage());
53 | }
54 | }
55 |
56 | @Override
57 | public void handleNotification(Notification notification, Object handback) {
58 |
59 | String notifType = notification.getType();
60 | if (notifType.equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
61 | LOGGER.fine("MEMORY_COLLECTION_THRESHOLD_EXCEEDED");
62 | long survivorCollectionUsed = 0;
63 | try {
64 | survivorCollectionUsed = memoryPoolMxBeanHelper.getSurvivorCollectionUsed();
65 | } catch (Exception e) {
66 | LOGGER.fine("Unable to retrieve Survivor Collection Used.");
67 | }
68 | memorySurvivor.addSurvivors(survivorCollectionUsed);
69 | LOGGER.fine("Survivor Collection Used = " + Long.valueOf(survivorCollectionUsed).toString());
70 | try {
71 | LOGGER.fine("Survivor GC Count = " + gcMXBeanHelper.getNurseryGCCount());
72 | } catch (Exception e) {
73 | LOGGER.fine("Unable to retrieve Survivor GC Count.");
74 | }
75 | }
76 |
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/GCOverhead.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import io.top4j.javaagent.exception.MBeanInitException;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.util.logging.Logger;
23 |
24 | public class GCOverhead {
25 |
26 | volatile private double gcOverhead;
27 | private GCTimeBean gcTimeBean;
28 | private GarbageCollectorMXBeanHelper gcMXBeanHelper;
29 |
30 | private static final Logger LOGGER = Logger.getLogger(GCOverhead.class.getName());
31 |
32 | public GCOverhead(MBeanServerConnection mbsc) throws Exception {
33 |
34 | LOGGER.fine("Initialising GC Overhead....");
35 |
36 | // instantiate new GarbageCollectorMXBeanHelper and GCTimeBean
37 | try {
38 | this.gcMXBeanHelper = new GarbageCollectorMXBeanHelper(mbsc);
39 | this.gcTimeBean = new GCTimeBean(mbsc);
40 | } catch (Exception e) {
41 | throw new MBeanInitException(e, "Failed to initialise GC Overhead stats collector due to: " + e.getMessage());
42 | }
43 |
44 | }
45 |
46 | /**
47 | * Update GC Overhead.
48 | */
49 | public void update() {
50 |
51 | long systemTime = System.currentTimeMillis();
52 | long gcTime;
53 | long intervalGCTime;
54 | long intervalSystemTime;
55 |
56 | gcTime = gcMXBeanHelper.getGCTime();
57 | intervalGCTime = gcTime - gcTimeBean.getLastGCTime();
58 | intervalSystemTime = systemTime - gcTimeBean.getLastSystemTime();
59 | LOGGER.finer("GC Overhead Interval GC Time = " + intervalGCTime);
60 | LOGGER.finer("GC Overhead Interval System Time = " + intervalSystemTime);
61 | gcOverhead = calculateGCOverhead(intervalGCTime, intervalSystemTime);
62 | LOGGER.fine("GC Overhead = " + gcOverhead + "%");
63 | gcTimeBean.setLastGCTime(gcTime);
64 | gcTimeBean.setLastSystemTime(systemTime);
65 |
66 | }
67 |
68 | public double getGcOverhead() {
69 | return gcOverhead;
70 | }
71 |
72 | public void setGcOverhead(double gcOverhead) {
73 | this.gcOverhead = gcOverhead;
74 | }
75 |
76 | private double calculateGCOverhead(long intervalGCTime, long intervalSystemTime) {
77 |
78 | return ((double) intervalGCTime / intervalSystemTime) * 100;
79 |
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/GCPauseTime.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import io.top4j.javaagent.exception.MBeanInitException;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.util.logging.Logger;
23 |
24 | public class GCPauseTime {
25 |
26 | volatile private double meanNurseryGCTime;
27 | volatile private double meanTenuredGCTime;
28 | private GCTimeBean gcTimeBean;
29 | private GarbageCollectorMXBeanHelper gcMXBeanHelper;
30 |
31 | private static final Logger LOGGER = Logger.getLogger(GCPauseTime.class.getName());
32 |
33 | public GCPauseTime(MBeanServerConnection mbsc) throws Exception {
34 |
35 | LOGGER.fine("Initialising GC Pause Time....");
36 |
37 | // instantiate new GarbageCollectorMXBeanHelper and GCTimeBean
38 | try {
39 | this.gcMXBeanHelper = new GarbageCollectorMXBeanHelper(mbsc);
40 | this.gcTimeBean = new GCTimeBean(mbsc);
41 | } catch (Exception e) {
42 | throw new MBeanInitException(e, "Failed to initialise GC Pause Time stats collector due to: " + e.getMessage());
43 | }
44 |
45 | }
46 |
47 | /**
48 | * Update GC Pause Time.
49 | */
50 | public void update() {
51 |
52 | long nurseryGCCount = 0;
53 | long nurseryGCTime = 0;
54 | long tenuredGCCount = 0;
55 | long tenuredGCTime = 0;
56 | long intervalNurseryGCTime;
57 | long intervalNurseryGCCount;
58 | long intervalTenuredGCTime;
59 | long intervalTenuredGCCount;
60 |
61 | try {
62 | // calculate mean nursery GC pause time
63 | nurseryGCTime = gcMXBeanHelper.getNurseryGCTime();
64 | intervalNurseryGCTime = nurseryGCTime - gcTimeBean.getLastNurseryGCTime();
65 | nurseryGCCount = gcMXBeanHelper.getNurseryGCCount();
66 | intervalNurseryGCCount = nurseryGCCount - gcTimeBean.getLastNurseryGCCount();
67 | if (intervalNurseryGCCount > 0) {
68 | meanNurseryGCTime = (double) intervalNurseryGCTime / intervalNurseryGCCount;
69 | }
70 | LOGGER.fine("Mean Nursery GC Time = " + meanNurseryGCTime + "ms");
71 | } catch (Exception e) {
72 | LOGGER.fine("WARNING: Unable to update nursery GC pause time due to: " + e.getMessage());
73 | }
74 | gcTimeBean.setLastNurseryGCTime(nurseryGCTime);
75 | gcTimeBean.setLastNurseryGCCount(nurseryGCCount);
76 |
77 | try {
78 | // calculate mean tenured GC pause time
79 | tenuredGCTime = gcMXBeanHelper.getTenuredGCTime();
80 | intervalTenuredGCTime = tenuredGCTime - gcTimeBean.getLastTenuredGCTime();
81 | tenuredGCCount = gcMXBeanHelper.getTenuredGCCount();
82 | intervalTenuredGCCount = tenuredGCCount - gcTimeBean.getLastTenuredGCCount();
83 | if (intervalTenuredGCCount > 0) {
84 | meanTenuredGCTime = (double) intervalTenuredGCTime / intervalTenuredGCCount;
85 | }
86 | LOGGER.fine("Mean Tenured GC Time = " + meanTenuredGCTime + "ms");
87 | } catch (Exception e) {
88 | LOGGER.fine("WARNING: Unable to update tenured GC pause time due to: " + e.getMessage());
89 | }
90 | gcTimeBean.setLastTenuredGCTime(tenuredGCTime);
91 | gcTimeBean.setLastTenuredGCCount(tenuredGCCount);
92 |
93 | }
94 |
95 | public double getMeanNurseryGCTime() {
96 | return meanNurseryGCTime;
97 | }
98 |
99 | public void setMeanNurseryGCTime(double meanNurseryGCTime) {
100 | this.meanNurseryGCTime = meanNurseryGCTime;
101 | }
102 |
103 | public double getMeanTenuredGCTime() {
104 | return meanTenuredGCTime;
105 | }
106 |
107 | public void setMeanTenuredGCTime(double meanTenuredGCTime) {
108 | this.meanTenuredGCTime = meanTenuredGCTime;
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/GCStats.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import io.top4j.javaagent.profiler.CpuTime;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.util.logging.*;
23 |
24 |
25 | public class GCStats implements GCStatsMXBean {
26 |
27 | private GCOverhead gcOverhead;
28 | private GCPauseTime gcPauseTime;
29 | private CpuTime cpuTime = new CpuTime();
30 | private double mBeanCpuTime;
31 | private boolean enabled = true;
32 | private String failureReason;
33 |
34 | private static final Logger LOGGER = Logger.getLogger(GCStats.class.getName());
35 |
36 | public GCStats(MBeanServerConnection mbsc) throws Exception {
37 |
38 | LOGGER.fine("Initialising GC stats....");
39 |
40 | // instantiate new GC Overhead
41 | GCOverhead gcOverhead = new GCOverhead(mbsc);
42 |
43 | // instantiate new GC Pause Time
44 | GCPauseTime gcPauseTime = new GCPauseTime(mbsc);
45 |
46 | this.gcOverhead = gcOverhead;
47 | this.gcPauseTime = gcPauseTime;
48 |
49 | }
50 |
51 | /**
52 | * Update GC stats.
53 | */
54 | public synchronized void update() {
55 |
56 | if (enabled) {
57 | try {
58 | // update GC stats
59 | updateGCStats();
60 | } catch (Exception e) {
61 | // something went wrong - record failure reason and disable any further updates
62 | this.failureReason = e.getMessage();
63 | this.enabled = false;
64 | LOGGER.severe("TOP4J ERROR: Failed to update GCStats MBean due to: " + e.getMessage());
65 | LOGGER.severe("TOP4J ERROR: Further GCStats MBean updates will be disabled from now on.");
66 | }
67 | }
68 |
69 | }
70 |
71 | private synchronized void updateGCStats() {
72 |
73 | // initialise thread CPU timer
74 | cpuTime.init();
75 |
76 | LOGGER.fine("Updating GC stats....");
77 |
78 | // update GC Overhead
79 | gcOverhead.update();
80 |
81 | // update GC pause time stats
82 | gcPauseTime.update();
83 |
84 | // update GC stats CPU time
85 | mBeanCpuTime = cpuTime.getMillis();
86 |
87 | }
88 |
89 | @Override
90 | public void setMBeanCpuTime(double agentCpuTime) {
91 | this.mBeanCpuTime = agentCpuTime;
92 | }
93 |
94 | @Override
95 | public double getMBeanCpuTime() {
96 | return mBeanCpuTime;
97 | }
98 |
99 | @Override
100 | public void setEnabled(boolean enabled) {
101 | this.enabled = enabled;
102 | }
103 |
104 | @Override
105 | public boolean getEnabled() {
106 | return this.enabled;
107 | }
108 |
109 | @Override
110 | public void setFailureReason(String failureReason) {
111 | this.failureReason = failureReason;
112 | }
113 |
114 | @Override
115 | public String getFailureReason() {
116 | return this.failureReason;
117 | }
118 |
119 | @Override
120 | public void setGcOverhead(double gcOverhead) {
121 | this.gcOverhead.setGcOverhead(gcOverhead);
122 |
123 | }
124 |
125 | @Override
126 | public double getGcOverhead() {
127 | return this.gcOverhead.getGcOverhead();
128 | }
129 |
130 | @Override
131 | public void setMeanNurseryGCTime(double meanNurseryGCTime) {
132 | this.gcPauseTime.setMeanNurseryGCTime(meanNurseryGCTime);
133 | }
134 |
135 | @Override
136 | public double getMeanNurseryGCTime() {
137 | return this.gcPauseTime.getMeanNurseryGCTime();
138 | }
139 |
140 | @Override
141 | public void setMeanTenuredGCTime(double meanTenuredGCTime) {
142 | gcPauseTime.setMeanTenuredGCTime(meanTenuredGCTime);
143 | }
144 |
145 | @Override
146 | public double getMeanTenuredGCTime() {
147 | return this.gcPauseTime.getMeanTenuredGCTime();
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/GCStatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | /**
22 | * Used to store and expose stats relating to the performance of the JVM Garbage Collector.
23 | */
24 |
25 | public interface GCStatsMXBean extends StatsMXBean {
26 |
27 | /**
28 | * Sets the GC overhead which is calculated as the percentage of real time (wall clock time) the JVM spends in garbage collection.
29 | *
30 | * Only stop-the-world garbage collection pauses contribute to the GC overhead. This, therefore, equates to the percentage of real time
31 | * that the application is stopped whilst garbage collection takes place. This is a key performance indicator of the impact of garbage collection
32 | * on a running Java application. A high GC overhead overhead can lead to poor application performance as there is less time available to process
33 | * application tasks and application threads can be blocked waiting to allocate memory (i.e. create objects).
34 | * @param gcOverhead the GC overhead
35 | */
36 | void setGcOverhead(double gcOverhead);
37 |
38 | /**
39 | * Returns the GC overhead which is calculated as the percentage of real time (wall clock time) the JVM spends in garbage collection.
40 | *
41 | * Only stop-the-world garbage collection pauses contribute to the GC overhead. This, therefore, equates to the percentage of real time
42 | * that the application is stopped whilst garbage collection takes place. This is a key performance indicator of the impact of garbage collection
43 | * on a running Java application. A high GC overhead overhead can lead to poor application performance as there is less time available to process
44 | * application tasks and application threads can be blocked waiting to allocate memory (i.e. create objects).
45 | * @return the GC overhead
46 | */
47 | double getGcOverhead();
48 |
49 | /**
50 | * Sets the mean time in milliseconds spent during a single nursery or eden or new stop-the-world GC event during the last iteration.
51 | * This time is not available for application processing and should therefore be kept to a minimum.
52 | * @param meanNurseryGCTime the mean nursery GC time in milliseconds
53 | */
54 | void setMeanNurseryGCTime(double meanNurseryGCTime);
55 |
56 | /**
57 | * Returns the mean time in milliseconds spent during a single nursery or eden or new stop-the-world GC event during the last iteration.
58 | * This time is not available for application processing and should therefore be kept to a minimum.
59 | * @return the mean nursery GC time in milliseconds
60 | */
61 | double getMeanNurseryGCTime();
62 |
63 | /**
64 | * Sets the mean time in milliseconds spent during a single tenured or full or old stop-the-world GC event during the last iteration.
65 | * This time is not available for application processing and should therefore be kept to a minimum.
66 | * @param meanTenuredGCTime the mean tenured GC time in milliseconds
67 | */
68 | void setMeanTenuredGCTime(double meanTenuredGCTime);
69 |
70 | /**
71 | * Returns the mean time in milliseconds spent during a single tenured or full or old stop-the-world GC event during the last iteration.
72 | * This time is not available for application processing and should therefore be kept to a minimum.
73 | * @return the mean tenured GC time in milliseconds
74 | */
75 | double getMeanTenuredGCTime();
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/gc/GCTimeBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.gc;
18 |
19 | import javax.management.MBeanServerConnection;
20 | import java.io.IOException;
21 | import java.lang.management.*;
22 | import java.util.List;
23 |
24 | public class GCTimeBean {
25 |
26 | private long lastGCTime;
27 | private long lastGCCount;
28 | private long lastNurseryGCTime;
29 | private long lastNurseryGCCount;
30 | private long lastTenuredGCTime;
31 | private long lastTenuredGCCount;
32 | private long lastSystemTime;
33 |
34 | public GCTimeBean(MBeanServerConnection mbsc) throws IOException {
35 |
36 | final List gcbeans =
37 | ManagementFactory.getPlatformMXBeans(mbsc, GarbageCollectorMXBean.class);
38 | long currentGCTime = 0;
39 | long currentGCCount = 0;
40 | long currentNurseryGCTime = 0;
41 | long currentNurseryGCCount = 0;
42 | long currentTenuredGCTime = 0;
43 | long currentTenuredGCCount = 0;
44 | for (GarbageCollectorMXBean gcbean : gcbeans) {
45 | String name = gcbean.getName();
46 | if (name.equals("Copy") || name.equals("PS Scavenge")) {
47 | currentNurseryGCTime = gcbean.getCollectionTime();
48 | currentNurseryGCCount = gcbean.getCollectionCount();
49 | }
50 | if (name.equals("MarkSweepCompact") || name.equals("PS MarkSweep")) {
51 | currentTenuredGCTime = gcbean.getCollectionTime();
52 | currentTenuredGCCount = gcbean.getCollectionCount();
53 | }
54 | currentGCTime += gcbean.getCollectionTime();
55 | currentGCCount += gcbean.getCollectionCount();
56 | }
57 | this.setLastGCTime(currentGCTime);
58 | this.setLastGCCount(currentGCCount);
59 | this.setLastNurseryGCTime(currentNurseryGCTime);
60 | this.setLastNurseryGCCount(currentNurseryGCCount);
61 | this.setLastTenuredGCTime(currentTenuredGCTime);
62 | this.setLastTenuredGCCount(currentTenuredGCCount);
63 | this.setLastSystemTime(System.currentTimeMillis());
64 |
65 | }
66 |
67 | public void setLastGCTime(long lastGCTime) {
68 | this.lastGCTime = lastGCTime;
69 | }
70 |
71 | public long getLastGCTime() {
72 | return lastGCTime;
73 | }
74 |
75 | public void setLastSystemTime(long lastSystemTime) {
76 | this.lastSystemTime = lastSystemTime;
77 | }
78 |
79 | public long getLastSystemTime() {
80 | return lastSystemTime;
81 | }
82 |
83 | public void setLastGCCount(long lastGCCount) {
84 | this.lastGCCount = lastGCCount;
85 | }
86 |
87 | public long getLastGCCount() {
88 | return lastGCCount;
89 | }
90 |
91 | public void setLastNurseryGCTime(long lastNurseryGCTime) {
92 | this.lastNurseryGCTime = lastNurseryGCTime;
93 | }
94 |
95 | public long getLastNurseryGCTime() {
96 | return lastNurseryGCTime;
97 | }
98 |
99 | public void setLastNurseryGCCount(long lastNurseryGCCount) {
100 | this.lastNurseryGCCount = lastNurseryGCCount;
101 | }
102 |
103 | public long getLastNurseryGCCount() {
104 | return lastNurseryGCCount;
105 | }
106 |
107 | public void setLastTenuredGCTime(long lastTenuredGCTime) {
108 | this.lastTenuredGCTime = lastTenuredGCTime;
109 | }
110 |
111 | public long getLastTenuredGCTime() {
112 | return lastTenuredGCTime;
113 | }
114 |
115 | public void setLastTenuredGCCount(long lastTenuredGCCount) {
116 | this.lastTenuredGCCount = lastTenuredGCCount;
117 | }
118 |
119 | public long getLastTenuredGCCount() {
120 | return lastTenuredGCCount;
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/heap/HeapStats.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.heap;
18 |
19 | import io.top4j.javaagent.exception.MBeanRuntimeException;
20 | import io.top4j.javaagent.profiler.CpuTime;
21 |
22 | import javax.management.MBeanServerConnection;
23 | import java.util.logging.Logger;
24 |
25 | public class HeapStats implements HeapStatsMXBean {
26 |
27 | private HeapUtilisation heapUtilisation;
28 | private CpuTime cpuTime = new CpuTime();
29 | private double mBeanCpuTime;
30 | private boolean enabled = true;
31 | private String failureReason;
32 |
33 | private static final Logger LOGGER = Logger.getLogger(HeapStats.class.getName());
34 |
35 | public HeapStats(MBeanServerConnection mbsc) throws Exception {
36 |
37 | LOGGER.fine("Initialising Heap Stats....");
38 |
39 | // instantiate new HeapUtilisation to store heap utilisation
40 | this.heapUtilisation = new HeapUtilisation(mbsc);
41 |
42 | }
43 |
44 | /**
45 | * Update Heap stats.
46 | */
47 | public synchronized void update() {
48 |
49 | if (enabled) {
50 | try {
51 | // update heap stats
52 | updateHeapStats();
53 | } catch (Exception e) {
54 | // something went wrong - record failure reason and disable any further updates
55 | this.failureReason = e.getMessage();
56 | this.enabled = false;
57 | LOGGER.severe("TOP4J ERROR: Failed to update HeapStats MBean due to: " + e.getMessage());
58 | LOGGER.severe("TOP4J ERROR: Further HeapStats MBean updates will be disabled from now on.");
59 | }
60 | }
61 | }
62 |
63 | private synchronized void updateHeapStats() throws MBeanRuntimeException {
64 |
65 | // initialise thread CPU timer
66 | cpuTime.init();
67 |
68 | LOGGER.fine("Updating Heap stats....");
69 |
70 | // update heap utilisation
71 | this.heapUtilisation.update();
72 |
73 | // update heap stats CPU time
74 | mBeanCpuTime = cpuTime.getMillis();
75 |
76 | }
77 |
78 | @Override
79 | public void setMBeanCpuTime(double agentCpuTime) {
80 | this.mBeanCpuTime = agentCpuTime;
81 | }
82 |
83 | @Override
84 | public double getMBeanCpuTime() {
85 | return mBeanCpuTime;
86 | }
87 |
88 | @Override
89 | public void setEdenSpaceUtil(double edenSpaceUtil) {
90 | this.heapUtilisation.setEdenSpaceUtil(edenSpaceUtil);
91 | }
92 |
93 | @Override
94 | public double getEdenSpaceUtil() {
95 | return this.heapUtilisation.getEdenSpaceUtil();
96 | }
97 |
98 | @Override
99 | public void setSurvivorSpaceUtil(double survivorSpaceUtil) {
100 | this.heapUtilisation.setSurvivorSpaceUtil(survivorSpaceUtil);
101 | }
102 |
103 | @Override
104 | public double getSurvivorSpaceUtil() {
105 | return this.heapUtilisation.getSurvivorSpaceUtil();
106 | }
107 |
108 | @Override
109 | public void setTenuredHeapUtil(double tenuredHeapUtil) {
110 | this.heapUtilisation.setTenuredHeapUtil(tenuredHeapUtil);
111 | }
112 |
113 | @Override
114 | public double getTenuredHeapUtil() {
115 | return this.heapUtilisation.getTenuredHeapUtil();
116 | }
117 |
118 | @Override
119 | public void setEnabled(boolean enabled) {
120 | this.enabled = enabled;
121 | }
122 |
123 | @Override
124 | public boolean getEnabled() {
125 | return this.enabled;
126 | }
127 |
128 | @Override
129 | public void setFailureReason(String failureReason) {
130 | this.failureReason = failureReason;
131 | }
132 |
133 | @Override
134 | public String getFailureReason() {
135 | return this.failureReason;
136 | }
137 |
138 | public boolean isSingleGenerationHeap() {
139 | return this.heapUtilisation.isSingleGenerationHeap();
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/heap/HeapStatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.heap;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | /**
22 | * Used to store and expose stats relating to the JVM heap utilisation. The heap utilisation is calculated as the percentage of heap used following the most recent garbage collection event. In other words.... ( heapUsed / heapCommitted ) * 100.
23 | */
24 |
25 | public interface HeapStatsMXBean extends StatsMXBean {
26 |
27 | /**
28 | * Sets the eden (or nursery or new) heap space utilisation following the most recent garbage collection event.
29 | *
30 | * This is effectively the residual heap occupied by live objects within the eden space which can't be garbage collected because they are
31 | * still referenced by one or more other objects. The eden heap utilisation is typically very low as most objects created within the eden
32 | * heap space are either garbage collected (cleared up) or promoted to one of the survivor spaces at each nursery GC event.
33 | * @param edenSpaceUtil the eden heap space utilisation
34 | */
35 | void setEdenSpaceUtil(double edenSpaceUtil);
36 |
37 | /**
38 | * Returns the eden (or nursery or new) heap space utilisation following the most recent garbage collection event.
39 | *
40 | * This is effectively the residual heap occupied by live objects within the eden space which can't be garbage collected because they are
41 | * still referenced by one or more other objects. The eden heap utilisation is typically very low as most objects created within the eden
42 | * heap space are either garbage collected (cleared up) or promoted to one of the survivor spaces at each nursery GC event.
43 | * @return the eden heap space utilisation
44 | */
45 | double getEdenSpaceUtil();
46 |
47 | /**
48 | * Sets the survivor heap space utilisation following the most recent garbage collection event.
49 | *
50 | * This is effectively the residual heap occupied by live objects within the survivor spaces which can't be garbage collected because they are
51 | * still referenced by one or more other objects.
52 | * @param survivorSpaceUtil the survivor heap space utilisation
53 | */
54 | void setSurvivorSpaceUtil(double survivorSpaceUtil);
55 |
56 | /**
57 | * Returns the survivor heap space utilisation following the most recent garbage collection event.
58 | *
59 | * This is effectively the residual heap occupied by live objects within the survivor spaces which can't be garbage collected because they are
60 | * still referenced by one or more other objects.
61 | * @return the survivor heap space utilisation
62 | */
63 | double getSurvivorSpaceUtil();
64 |
65 | /**
66 | * Sets the tenured (or old) heap space utilisation following the most recent garbage collection event.
67 | * This is effectively the residual heap occupied by live objects within the tenured (or old) space which can't be garbage collected because they are
68 | * still referenced by one or more other objects. High tenured heap space utilisation can be an indication that the JVM is running low on memory.
69 | * A high tenured heap utilisation can lead to frequent garbage collection events which will typically lead to a high GC overhead and therefore poor
70 | * application performance/memory throughput. See GCOverhead attribute above for more details.
71 | * @param tenuredHeapUtil the tenured heap space utilisation
72 | */
73 | void setTenuredHeapUtil(double tenuredHeapUtil);
74 |
75 | /**
76 | * Returns the tenured (or old) heap space utilisation following the most recent garbage collection event.
77 | *
78 | * This is effectively the residual heap occupied by live objects within the tenured (or old) space which can't be garbage collected because they are
79 | * still referenced by one or more other objects. High tenured heap space utilisation can be an indication that the JVM is running low on memory.
80 | * A high tenured heap utilisation can lead to frequent garbage collection events which will typically lead to a high GC overhead and therefore poor
81 | * application performance/memory throughput. See GCOverhead attribute above for more details.
82 | * @return the tenured heap space utilisation
83 | */
84 | double getTenuredHeapUtil();
85 |
86 | /**
87 | * @return true if the heap is a single-generation (thus no survivor/tenured generations).
88 | */
89 | boolean isSingleGenerationHeap();
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/memory/MemoryStatsMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.memory;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | /**
22 | * Used to store and expose stats relating to the JVM memory pool usage.
23 | */
24 |
25 | public interface MemoryStatsMXBean extends StatsMXBean {
26 |
27 | /**
28 | * Sets the memory allocation rate which represents the amount of memory consumed by the Java application whilst creating new objects over time.
29 | * It is measured in MB per second (MB/s). A high memory allocation rate can be an indication that the Java application is creating too many new
30 | * objects and as a result putting pressure on the JVM memory management sub-system which can cause more frequent GC events and associated GC overhead.
31 | * @param memoryAllocationRate the memory allocation rate in MB/s
32 | */
33 | void setMemoryAllocationRate(double memoryAllocationRate);
34 |
35 | /**
36 | * Returns the memory allocation rate which represents the amount of memory consumed by the Java application whilst creating new objects over time.
37 | * It is measured in MB per second (MB/s). A high memory allocation rate can be an indication that the Java application is creating too many new
38 | * objects and as a result putting pressure on the JVM memory management sub-system which can cause more frequent GC events and associated GC overhead.
39 | * @return the memory allocation rate in MB/s
40 | */
41 | double getMemoryAllocationRate();
42 |
43 | /**
44 | * Sets the memory survivor rate represents the amount of memory that survives a nursery (or new) GC event and is promoted to one of the survivor spaces over time.
45 | * It is measured in MB per second (MB/s). A high memory survivor rate can be an indication that too many objects are being promoted to the survivor spaces which
46 | * can be an indication that the eden space is undersized or the memory allocation rate (to eden) is too high.
47 | * @param memorySurvivorRate the memory survivor rate in MB/s
48 | */
49 | void setMemorySurvivorRate(double memorySurvivorRate);
50 |
51 | /**
52 | * Returns the memory survivor rate represents the amount of memory that survives a nursery (or new) GC event and is promoted to one of the survivor spaces over time.
53 | * It is measured in MB per second (MB/s). A high memory survivor rate can be an indication that too many objects are being promoted to the survivor spaces which
54 | * can be an indication that the eden space is undersized or the memory allocation rate (to eden) is too high.
55 | * @return the memory survivor rate in MB/s
56 | */
57 | double getMemorySurvivorRate();
58 |
59 | /**
60 | * Sets the memory promotion rate represents the amount of memory that survives one or more nursery (or new) GC events and is promoted to the tenured (or old) space over time.
61 | * It is measured in MB per second (MB/s). A high memory promotion rate can be an indication that too many objects are being promoted to the tenured space which
62 | * can be an indication that the eden space is undersized or the memory allocation rate (to eden) is too high.
63 | * @param memoryPromotionRate the memory promotion rate in MB/s
64 | */
65 | void setMemoryPromotionRate(double memoryPromotionRate);
66 |
67 | /**
68 | * Returns the memory promotion rate represents the amount of memory that survives one or more nursery (or new) GC events and is promoted to the tenured (or old) space over time.
69 | * It is measured in MB per second (MB/s). A high memory promotion rate can be an indication that too many objects are being promoted to the tenured space which
70 | * can be an indication that the eden space is undersized or the memory allocation rate (to eden) is too high.
71 | * @return the memory promotion rate in MB/s
72 | */
73 | double getMemoryPromotionRate();
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/memory/MemorySurvivorBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.memory;
18 |
19 | public class MemorySurvivorBean {
20 |
21 | private long survivors;
22 | private long lastGCCount;
23 | private long lastSystemTime;
24 |
25 | public MemorySurvivorBean() {
26 |
27 | this.setSurvivors(0);
28 | this.setLastGCCount(0);
29 |
30 | }
31 |
32 | public synchronized long getSurvivors() {
33 | return survivors;
34 | }
35 |
36 | public synchronized void setSurvivors(long survivors) {
37 | this.survivors = survivors;
38 | }
39 |
40 | public synchronized void resetSurvivors() {
41 | this.survivors = 0;
42 | }
43 |
44 | public synchronized void addSurvivors(long survivors) {
45 | this.survivors += survivors;
46 | }
47 |
48 | public synchronized long getAndResetSurvivors() {
49 |
50 | long survivors = this.survivors;
51 | this.survivors = 0;
52 | return survivors;
53 |
54 | }
55 |
56 | public long getLastGCCount() {
57 | return lastGCCount;
58 | }
59 |
60 | public void setLastGCCount(long lastGCCount) {
61 | this.lastGCCount = lastGCCount;
62 | }
63 |
64 | public long getLastSystemTime() {
65 | return lastSystemTime;
66 | }
67 |
68 | public void setLastSystemTime(long lastSystemTime) {
69 | this.lastSystemTime = lastSystemTime;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/memory/MemorySurvivorRate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.memory;
18 |
19 | import java.lang.management.ManagementFactory;
20 | import java.lang.management.MemoryMXBean;
21 | import java.util.logging.Logger;
22 |
23 | import javax.management.MBeanServerConnection;
24 | import javax.management.NotificationEmitter;
25 |
26 | import io.top4j.javaagent.mbeans.jvm.gc.CollectionUsageListener;
27 |
28 | public class MemorySurvivorRate {
29 |
30 | volatile private double memorySurvivorRate;
31 | private MemorySurvivorBean memorySurvivor;
32 |
33 | private static final Logger LOGGER = Logger.getLogger(MemorySurvivorRate.class.getName());
34 |
35 | public MemorySurvivorRate(MBeanServerConnection mbsc) throws Exception {
36 |
37 | // instantiate new MemorySurvivorBean
38 | MemorySurvivorBean memorySurvivor = new MemorySurvivorBean();
39 |
40 | // instantiate new MemoryPoolMXBeanHelper
41 | MemoryPoolMXBeanHelper memoryPoolMxBeanHelper = new MemoryPoolMXBeanHelper(mbsc);
42 |
43 | // Register CollectionUsageListener with MemoryMXBean
44 | MemoryMXBean memoryMXBean = ManagementFactory.getPlatformMXBean(mbsc, MemoryMXBean.class);
45 | NotificationEmitter emitter = (NotificationEmitter) memoryMXBean;
46 | CollectionUsageListener listener = new CollectionUsageListener(mbsc, memorySurvivor);
47 | emitter.addNotificationListener(listener, null, null);
48 |
49 | long threshold = 1;
50 | memoryPoolMxBeanHelper.setSurvivorCollectionUsageThreshold(threshold);
51 |
52 | this.memorySurvivor = memorySurvivor;
53 |
54 | }
55 |
56 | public double getMemorySurvivorRate() {
57 | return memorySurvivorRate;
58 | }
59 |
60 | public void setMemorySurvivorRate(double memorySurvivorRate) {
61 | this.memorySurvivorRate = memorySurvivorRate;
62 | }
63 |
64 | /**
65 | * Update Memory Survivor Rate.
66 | */
67 | public void update() {
68 |
69 | long systemTime = System.currentTimeMillis();
70 | double intervalSystemTimeSecs;
71 | long intervalSurvivors;
72 |
73 | // calculate intervalSystemTimeSecs in seconds
74 | intervalSystemTimeSecs = ((double) systemTime - (double) memorySurvivor.getLastSystemTime()) / 1000;
75 | LOGGER.finest("Survivor Rate System Time = " + systemTime);
76 | LOGGER.finest("Survivor Rate Last System Time = " + memorySurvivor.getLastSystemTime());
77 |
78 | // get and reset intervalSurvivors
79 | intervalSurvivors = memorySurvivor.getAndResetSurvivors();
80 |
81 | // calculate memory survivor rate
82 | this.memorySurvivorRate = calculateMemorySurvivorRate(intervalSurvivors, intervalSystemTimeSecs);
83 |
84 | this.memorySurvivor.setLastSystemTime(systemTime);
85 |
86 | }
87 |
88 | private double calculateMemorySurvivorRate(long intervalSurvivors, double intervalSystemTimeSecs) {
89 |
90 | return ((double) intervalSurvivors / intervalSystemTimeSecs) / 1048576;
91 |
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/BlockedThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import io.top4j.javaagent.utils.ThreadHelper;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.io.IOException;
23 | import java.lang.Thread.State;
24 |
25 |
26 | public class BlockedThread implements BlockedThreadMXBean {
27 |
28 | volatile private String threadName;
29 | volatile private long threadId;
30 | volatile private State threadState;
31 | volatile private long threadBlockedTime;
32 | volatile private double threadBlockedPercentage;
33 | private ThreadHelper threadHelper;
34 |
35 | public BlockedThread(MBeanServerConnection mbsc) throws IOException {
36 |
37 | this.threadHelper = new ThreadHelper(mbsc);
38 |
39 | }
40 |
41 | public void setThreadName(String threadName) {
42 | this.threadName = threadName;
43 | }
44 |
45 | public String getThreadName() {
46 | return threadName;
47 | }
48 |
49 | public void setThreadId(long threadId) {
50 | this.threadId = threadId;
51 | }
52 |
53 | public long getThreadId() {
54 | return threadId;
55 | }
56 |
57 | public void setThreadState(State threadState) {
58 | this.threadState = threadState;
59 | }
60 |
61 | public State getThreadState() {
62 | return threadState;
63 | }
64 |
65 | @Override
66 | public void setThreadBlockedTime(long threadBlockedTime) {
67 |
68 | this.threadBlockedTime = threadBlockedTime;
69 |
70 | }
71 |
72 | @Override
73 | public long getThreadBlockedTime() {
74 | return threadBlockedTime;
75 | }
76 |
77 | @Override
78 | public void setThreadBlockedPercentage(double threadBlockedPercentage) {
79 |
80 | this.threadBlockedPercentage = threadBlockedPercentage;
81 |
82 | }
83 |
84 | @Override
85 | public double getThreadBlockedPercentage() {
86 | return threadBlockedPercentage;
87 | }
88 |
89 | public String getStackTrace(int maxDepth) {
90 |
91 | return threadHelper.getStackTrace(threadId, maxDepth);
92 |
93 | }
94 |
95 | public String getStackTraceWithContext(int maxDepth) {
96 |
97 | return threadHelper.getStackTraceWithContext(threadId, maxDepth);
98 |
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/BlockedThreadMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | /**
20 | * Used to store and expose stats relating to a thread that has been blocked for some time during the last iteration.
21 | * Each blocked thread is ranked between 1 and N via the "rank" attribute on the BlockedThread MBean Object Name,
22 | * where 1 is the thread that has been blocked the most and N is the thread that has been blocked the least
23 | * (out of the top ranked blocked threads).
24 | */
25 |
26 | public interface BlockedThreadMXBean {
27 |
28 | /**
29 | * Sets the name of the blocked thread.
30 | * @param threadName the thread name
31 | */
32 | public void setThreadName(String threadName);
33 |
34 | /**
35 | * Returns the name of the blocked thread.
36 | * @return the thread name
37 | */
38 | public String getThreadName();
39 |
40 | /**
41 | * Sets the thread ID of the blocked thread.
42 | * @param threadId the thread ID
43 | */
44 | public void setThreadId(long threadId);
45 |
46 | /**
47 | * Returns the thread ID of the blocked thread.
48 | * @return the thread ID
49 | */
50 | public long getThreadId();
51 |
52 | /**
53 | * Sets the thread state as defined by the java.lang.Thread.State Enum.
54 | * @param threadState the thread state
55 | */
56 | public void setThreadState(Thread.State threadState);
57 |
58 | /**
59 | * Sets the thread state as defined by the java.lang.Thread.State Enum.
60 | * @return the thread state
61 | */
62 | public Thread.State getThreadState();
63 |
64 | /**
65 | * Sets the time in milliseconds that the thread has been in a blocked state during the last iteration.
66 | * @param threadBlockedTime blocked time in milliseconds
67 | */
68 | public void setThreadBlockedTime(long threadBlockedTime);
69 |
70 | /**
71 | * Returns the time in milliseconds that the thread has been in a blocked state during the last iteration.
72 | * @return blocked time in milliseconds
73 | */
74 | public long getThreadBlockedTime();
75 |
76 | /**
77 | * Sets the percentage of time that the thread has been in a blocked state during the last iteration.
78 | *
79 | * A high thread blocked percentage can be an indicator of thread lock contention.
80 | * For example, threads blocked waiting to access a synchronised method or code block.
81 | * @param threadBlockedPercentage the thread blocked percentage
82 | */
83 | public void setThreadBlockedPercentage(double threadBlockedPercentage);
84 |
85 | /**
86 | * Returns the percentage of time that the thread has been in a blocked state during the last iteration.
87 | *
88 | * A high thread blocked percentage can be an indicator of thread lock contention.
89 | * For example, threads blocked waiting to access a synchronised method or code block.
90 | * @return the thread blocked percentage
91 | */
92 | public double getThreadBlockedPercentage();
93 |
94 | /**
95 | * Returns the stack trace for this blocked thread with a maximum frame depth of maxDepth.
96 | * @param maxDepth maximum frame depth
97 | * @return a String representation of the stack trace
98 | */
99 | public String getStackTrace(int maxDepth);
100 |
101 | /**
102 | * Returns the stack trace for this blocked thread with context, e.g. thread name and thread state, with a maximum frame depth of maxDepth.
103 | * @param maxDepth maximum frame depth
104 | * @return a String representation of the stack trace with some additional context
105 | */
106 | public String getStackTraceWithContext(int maxDepth);
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/HotMethod.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import io.top4j.javaagent.utils.ThreadHelper;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.io.IOException;
23 |
24 | public class HotMethod implements HotMethodMXBean {
25 |
26 | volatile private String methodName;
27 | volatile private String threadName;
28 | volatile private long threadId;
29 | volatile private double loadProfile;
30 | volatile private StackTraceElement[] stackTrace;
31 | private ThreadHelper threadHelper;
32 |
33 | public HotMethod(MBeanServerConnection mbsc) throws IOException {
34 |
35 | this.threadHelper = new ThreadHelper(mbsc);
36 |
37 | }
38 |
39 | @Override
40 | public void setMethodName(String methodName) {
41 | this.methodName = methodName;
42 | }
43 |
44 | @Override
45 | public String getMethodName() {
46 | return methodName;
47 | }
48 |
49 | @Override
50 | public void setThreadName(String threadName) {
51 | this.threadName = threadName;
52 | }
53 |
54 | @Override
55 | public String getThreadName() {
56 | return threadName;
57 | }
58 |
59 | @Override
60 | public void setThreadId(long threadId) {
61 | this.threadId = threadId;
62 | }
63 |
64 | @Override
65 | public long getThreadId() {
66 | return threadId;
67 | }
68 |
69 | @Override
70 | public void setLoadProfile(double loadProfile) {
71 | this.loadProfile = loadProfile;
72 | }
73 |
74 | @Override
75 | public double getLoadProfile() {
76 | return loadProfile;
77 | }
78 |
79 | @Override
80 | public String getStackTrace(int maxDepth) {
81 | return threadHelper.getStackTraceAsString(stackTrace);
82 | }
83 |
84 | public void setStackTrace(StackTraceElement[] stackTrace) {
85 | if (stackTrace != null) {
86 | this.stackTrace = stackTrace.clone();
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/HotMethodMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | /**
20 | * Used to store and expose stats relating to a Java method that has been determined to have executed frequently.
21 | */
22 |
23 | public interface HotMethodMXBean {
24 |
25 | /**
26 | * Sets the hot method name.
27 | * @param methodName the method name
28 | */
29 | void setMethodName(String methodName);
30 |
31 | /**
32 | * Returns the hot method name.
33 | * @return the method name
34 | */
35 | String getMethodName();
36 |
37 | /**
38 | * Sets the name of the thread that has executed the method most recently.
39 | * @param threadName the thread name
40 | */
41 | void setThreadName(String threadName);
42 |
43 | /**
44 | * Returns the name of the thread that has executed the method most recently.
45 | * @return the thread name
46 | */
47 | String getThreadName();
48 |
49 | /**
50 | * Sets the ID of the thread that has executed the method most recently.
51 | * @param threadId the thread ID
52 | */
53 | void setThreadId(long threadId);
54 |
55 | /**
56 | * Returns the ID of the thread that has executed the method most recently.
57 | * @return the thread ID
58 | */
59 | long getThreadId();
60 |
61 | /**
62 | * Sets the hot method load profile which is an indication of how hot the method has been during the last iteration.
63 | *
64 | * The load profile is calculated as the CPU time used by a top thread that has executed a hot method as
65 | * a percentage of the total CPU time used by all top threads during the last iteration.
66 | * @param loadProfile the load profile
67 | */
68 | void setLoadProfile(double loadProfile);
69 |
70 | /**
71 | * Returns the hot method load profile which is an indication of how hot the method has been during the last iteration.
72 | *
73 | * The load profile is calculated as the CPU time used by a top thread that has executed a hot method as
74 | * a percentage of the total CPU time used by all top threads during the last iteration.
75 | * @return the load profile
76 | */
77 | double getLoadProfile();
78 |
79 | /**
80 | * Returns the most recent stack trace for the hot method.
81 | * @param maxDepth the stack trace maximum frame depth
82 | * @return a String representation of the stack trace
83 | */
84 | String getStackTrace(int maxDepth);
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/HotMethodTracker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import io.top4j.javaagent.profiler.CpuTime;
20 |
21 | import java.util.Map;
22 | import java.util.TimerTask;
23 | import java.util.logging.Logger;
24 |
25 | public class HotMethodTracker extends TimerTask {
26 |
27 | private Map topThreadMap;
28 | private HotMethods hotMethods;
29 | private CpuTime cpuTime = new CpuTime();
30 |
31 | private static final Logger LOGGER = Logger.getLogger(HotMethodTracker.class.getName());
32 |
33 | public HotMethodTracker(Map topThreadMap, HotMethods hotMethods) {
34 |
35 | // store topThreadMap
36 | this.topThreadMap = topThreadMap;
37 | // store hotMethods
38 | this.hotMethods = hotMethods;
39 |
40 | }
41 |
42 | @Override
43 | public void run() {
44 |
45 | // initialise thread CPU timer
46 | cpuTime.init();
47 |
48 | // iterate over topThreadsMap
49 | for (TopThread topThread : topThreadMap.values()) {
50 |
51 | // get topThread stack trace
52 | StackTraceElement[] stackTrace = topThread.getStackTraceElements();
53 | // get topThread name
54 | String threadName = topThread.getThreadName();
55 | // get topThread Id
56 | long threadId = topThread.getThreadId();
57 | // get topThread state
58 | Thread.State threadState = topThread.getThreadState();
59 | if (stackTrace != null && threadName != null && threadId != 0 && threadState.equals(Thread.State.RUNNABLE)) {
60 | // add top thread stack trace, name and ID to hotMethods
61 | hotMethods.addHotMethod(topThread.getStackTraceElements(), topThread.getThreadName(), topThread.getThreadId());
62 | }
63 | }
64 |
65 | LOGGER.finer("Hot Method Tracker CPU Time: " + cpuTime.getMillis() + " ms");
66 | // update hot method tracker CPU time
67 | hotMethods.addMBeanCpuTime(cpuTime.getMillis());
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/MethodTimeMap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import java.util.*;
20 |
21 | public class MethodTimeMap {
22 |
23 | // Map key = method count, Map value = list of method names
24 | NavigableMap> methodTimeMap = new TreeMap<>();
25 |
26 | public void put(Long methodTime, String methodName) {
27 |
28 | // get list of method names with this methodTime
29 | List existingMethodNameList = methodTimeMap.get(methodTime);
30 |
31 | if (existingMethodNameList == null) {
32 |
33 | // create new methodNameList
34 | List newMethodNameList = new ArrayList<>();
35 | // add methodName to methodNameList
36 | newMethodNameList.add(methodName);
37 | // add methodTime and methodNameList to methodTimeMap
38 | methodTimeMap.put(methodTime, newMethodNameList);
39 |
40 | } else {
41 |
42 | // add methodName to methodNameList
43 | existingMethodNameList.add(methodName);
44 | // add methodTime and methodNameList to methodTimeMap
45 | methodTimeMap.put(methodTime, existingMethodNameList);
46 |
47 | }
48 |
49 | }
50 |
51 | public List get(long methodTime) {
52 |
53 | return methodTimeMap.get(methodTime);
54 |
55 | }
56 |
57 | public int size() {
58 |
59 | return methodTimeMap.size();
60 |
61 | }
62 |
63 | public NavigableSet descendingKeySet() {
64 |
65 | return methodTimeMap.descendingKeySet();
66 |
67 | }
68 |
69 | public String toString() {
70 |
71 | return methodTimeMap.toString();
72 |
73 | }
74 |
75 | public NavigableMap> getMethodTimeMap() {
76 |
77 | return methodTimeMap;
78 |
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/ThreadTimeMap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.NavigableMap;
22 | import java.util.NavigableSet;
23 | import java.util.TreeMap;
24 |
25 | public class ThreadTimeMap {
26 |
27 | // Map key = thread time, Map value = list of thread IDs
28 | NavigableMap> threadTimeMap = new TreeMap<>();
29 |
30 | public void put(Long threadTime, Long threadId) {
31 |
32 | // get list of thread IDs with this threadTime
33 | List existingThreadIdList = threadTimeMap.get(threadTime);
34 |
35 | if (existingThreadIdList == null) {
36 |
37 | // create new threadIdList
38 | List newThreadIdList = new ArrayList<>();
39 | // add threadId to threadIdList
40 | newThreadIdList.add(threadId);
41 | // add threadTime and threadIdList to threadTimeMap
42 | threadTimeMap.put(threadTime, newThreadIdList);
43 |
44 | } else {
45 |
46 | // add threadId to threadIdList
47 | existingThreadIdList.add(threadId);
48 | // add threadTime and threadIdList to threadTimeMap
49 | threadTimeMap.put(threadTime, existingThreadIdList);
50 |
51 | }
52 |
53 | }
54 |
55 | public List get(Long threadTime) {
56 |
57 | return threadTimeMap.get(threadTime);
58 |
59 | }
60 |
61 | public int size() {
62 |
63 | return threadTimeMap.size();
64 |
65 | }
66 |
67 | public NavigableSet descendingKeySet() {
68 |
69 | return threadTimeMap.descendingKeySet();
70 |
71 | }
72 |
73 | public String toString() {
74 |
75 | return threadTimeMap.toString();
76 |
77 | }
78 |
79 | public NavigableMap> getThreadTimeMap() {
80 |
81 | return threadTimeMap;
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/TopThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | import io.top4j.javaagent.utils.ThreadHelper;
20 |
21 | import javax.management.MBeanServerConnection;
22 | import java.io.IOException;
23 | import java.lang.Thread.State;
24 | import java.lang.management.ThreadInfo;
25 |
26 |
27 | public class TopThread implements TopThreadMXBean {
28 |
29 | volatile private String threadName;
30 | volatile private long threadId;
31 | volatile private State threadState;
32 | volatile private double threadCpuUsage;
33 | private ThreadHelper threadHelper;
34 | private ThreadInfo threadInfo;
35 |
36 | public TopThread(MBeanServerConnection mbsc) throws IOException {
37 |
38 | this.threadHelper = new ThreadHelper(mbsc);
39 |
40 | }
41 |
42 | public void setThreadName(String threadName) {
43 | this.threadName = threadName;
44 | }
45 |
46 | public String getThreadName() {
47 | return threadName;
48 | }
49 |
50 | public void setThreadId(long threadId) {
51 | this.threadId = threadId;
52 | }
53 |
54 | public long getThreadId() {
55 | return threadId;
56 | }
57 |
58 | public void setThreadState(State threadState) {
59 | this.threadState = threadState;
60 | }
61 |
62 | public State getThreadState() {
63 |
64 | // get current thread state
65 | State threadState = threadHelper.getThreadState(threadId);
66 | if (threadState != null) {
67 | // return current thread state
68 | return threadState;
69 | } else {
70 | // return cached thread state
71 | return this.threadState;
72 | }
73 | }
74 |
75 | public void setThreadCpuUsage(double threadCpuUsage) {
76 | this.threadCpuUsage = threadCpuUsage;
77 | }
78 |
79 | public double getThreadCpuUsage() {
80 | return threadCpuUsage;
81 | }
82 |
83 | public String getStackTrace(int maxDepth) {
84 |
85 | return threadHelper.getStackTrace(threadId, maxDepth);
86 |
87 | }
88 |
89 | public String getStackTraceWithContext(int maxDepth) {
90 |
91 | return threadHelper.getStackTraceWithContext(threadId, maxDepth);
92 |
93 | }
94 |
95 | public StackTraceElement[] getStackTraceElements(int maxDepth) {
96 |
97 | return threadHelper.getStackTraceElements(threadId, maxDepth);
98 |
99 | }
100 |
101 | public StackTraceElement[] getStackTraceElements() {
102 |
103 | return threadHelper.getStackTraceElements(threadId);
104 |
105 | }
106 |
107 | public ThreadInfo getThreadInfo() {
108 | return threadInfo;
109 | }
110 |
111 | public void setThreadInfo(ThreadInfo threadInfo) {
112 | this.threadInfo = threadInfo;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/jvm/threads/TopThreadMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.jvm.threads;
18 |
19 | /**
20 | * Used to store and expose stats relating to a thread that has been determined as a top CPU consumer during the last iteration.
21 | * Each top thread is ranked between 1 and N via the "rank" attribute on the TopThread MBean Object Name, where 1 is the thread
22 | * that has consumed the most CPU and N is the thread that has consumed the least (out of the top ranked threads).
23 | */
24 |
25 | public interface TopThreadMXBean {
26 |
27 | /**
28 | * Sets the name of the top thread.
29 | * @param threadName the thread name
30 | */
31 | void setThreadName(String threadName);
32 |
33 | /**
34 | * Returns the name of the top thread.
35 | * @return the thread name
36 | */
37 | String getThreadName();
38 |
39 | /**
40 | * Sets the thread ID of the top thread.
41 | * @param threadId the thread ID
42 | */
43 | void setThreadId(long threadId);
44 |
45 | /**
46 | * Returns the thread ID of the top thread.
47 | * @return the thread ID
48 | */
49 | long getThreadId();
50 |
51 | /**
52 | * Sets the thread state as defined by the java.lang.Thread.State Enum.
53 | * @param threadState the thread state
54 | */
55 | void setThreadState(Thread.State threadState);
56 |
57 | /**
58 | * Returns the thread state as defined by the java.lang.Thread.State Enum.
59 | * @return the thread state
60 | */
61 | Thread.State getThreadState();
62 |
63 | /**
64 | * Sets the thread CPU time as a percentage of the total CPU time available during the last iteration.
65 | *
66 | * The thread CPU usage is calculated as the total CPU time consumed by a thread divided by the total CPU time available (wall clock time) multiplied by 100.
67 | * In other words.... ( threadCpuTime / elapsedTime ) * 100
68 | * @param threadCpuUsage the thread CPU usage
69 | */
70 | void setThreadCpuUsage(double threadCpuUsage);
71 |
72 | /**
73 | * Returns the thread CPU time as a percentage of the total CPU time available during the last iteration.
74 | *
75 | * The thread CPU usage is calculated as the total CPU time consumed by a thread divided by the total CPU time available (wall clock time) multiplied by 100.
76 | * In other words.... ( threadCpuTime / elapsedTime ) * 100
77 | * @return the thread CPU usage
78 | */
79 | double getThreadCpuUsage();
80 |
81 | /**
82 | * Returns the stack trace for this top thread with a maximum frame depth of maxDepth.
83 | * @param maxDepth maximum frame depth
84 | * @return a String representation of the stack trace
85 | */
86 | String getStackTrace(int maxDepth);
87 |
88 | /**
89 | * Returns the stack trace for this blocked thread with context, e.g. thread name and thread state, with a maximum frame depth of maxDepth.
90 | * @param maxDepth maximum frame depth
91 | * @return a String representation of the stack trace with some additional context
92 | */
93 | String getStackTraceWithContext(int maxDepth);
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/logger/StatsLogWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.logger;
18 |
19 | import java.io.File;
20 | import java.io.FileOutputStream;
21 | import java.io.IOException;
22 | import java.io.PrintWriter;
23 | import java.util.logging.Logger;
24 |
25 | public class StatsLogWriter {
26 |
27 | private PrintWriter printWriter;
28 | private FileOutputStream fileOutputStream;
29 | private String fileName;
30 |
31 | private static final Logger LOGGER = Logger.getLogger(StatsLogWriter.class.getName());
32 |
33 | public StatsLogWriter(String fileName) throws Exception {
34 |
35 | // init new PrintWriter
36 | init(fileName, null);
37 | }
38 |
39 | public StatsLogWriter(String fileName, String header) throws Exception {
40 |
41 | // init new PrintWriter
42 | init(fileName, header);
43 | }
44 |
45 | private void init(String fileName, String header) throws Exception {
46 |
47 | PrintWriter printWriter = null;
48 |
49 | File file = new File(fileName);
50 | try {
51 | if (!file.exists()) {
52 | // create new file
53 | LOGGER.finer("Creating new stats log file " + fileName);
54 | if (header != null) {
55 | printWriter = createNewFile(file, header);
56 | } else {
57 | printWriter = createNewFile(file, null);
58 | }
59 | } else {
60 | // create new printWriter
61 | LOGGER.finer("Stats log file " + fileName + " already exists.");
62 | fileOutputStream = new FileOutputStream(fileName, true);
63 | printWriter = new PrintWriter(fileOutputStream);
64 | }
65 |
66 | } catch (IOException ioe) {
67 | throw new IllegalAccessException("Unable to create stats log file " + fileName + " due to: " + ioe.getMessage());
68 | }
69 |
70 | // store print writer
71 | this.printWriter = printWriter;
72 |
73 | // store file name
74 | this.fileName = fileName;
75 |
76 | }
77 |
78 | private PrintWriter createNewFile(File file, String header) throws Exception {
79 |
80 | PrintWriter printWriter = null;
81 | try {
82 | file.createNewFile();
83 | printWriter = new PrintWriter(new FileOutputStream(file.getAbsolutePath(), true));
84 | if (header != null) {
85 | printWriter.println(header);
86 | }
87 | } catch (IOException ioe) {
88 | throw new IllegalAccessException("Unable to create stats log file " + fileName + " due to: " + ioe.getMessage());
89 | } finally {
90 | if (printWriter != null) {
91 | printWriter.flush();
92 | }
93 | }
94 | return printWriter;
95 | }
96 |
97 | public void println(String logEntry) {
98 |
99 | if (printWriter != null) {
100 | // write logEntry to stats log file via printWriter
101 | printWriter.println(logEntry);
102 | // and flush to disk
103 | printWriter.flush();
104 | }
105 | }
106 |
107 | public void close() {
108 |
109 | if (printWriter != null) {
110 | // close the printWriter
111 | printWriter.close();
112 | }
113 | if (fileOutputStream != null) {
114 | // and the fileOutputStream
115 | try {
116 | fileOutputStream.close();
117 | } catch (IOException ioe) {
118 | LOGGER.severe("Unable to close file output stream for stats log file " + fileName + " due to: " + ioe.getMessage());
119 | }
120 | }
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/mbeans/logger/StatsLoggerMXBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.mbeans.logger;
18 |
19 | import io.top4j.javaagent.mbeans.StatsMXBean;
20 |
21 | public interface StatsLoggerMXBean extends StatsMXBean {
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/messaging/LoggerQueue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.messaging;
18 |
19 | import java.util.concurrent.LinkedBlockingQueue;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.logging.Logger;
22 |
23 | public class LoggerQueue {
24 |
25 | private LinkedBlockingQueue loggerQueue;
26 |
27 | private static final Logger LOGGER = Logger.getLogger(LoggerQueue.class.getName());
28 |
29 | public LoggerQueue(int capacity) {
30 |
31 | this.loggerQueue = new LinkedBlockingQueue<>(capacity);
32 |
33 | }
34 |
35 | public boolean send(String notification) {
36 |
37 | // send notification to loggerQueue
38 | return loggerQueue.offer(notification);
39 |
40 | }
41 |
42 | public boolean hasElements() {
43 |
44 | // test if the loggerQueue has elements
45 | if (loggerQueue.isEmpty()) {
46 | return false;
47 | } else {
48 | return true;
49 | }
50 |
51 | }
52 |
53 | public int size() {
54 |
55 | // return the size of the loggerQueue
56 | return loggerQueue.size();
57 |
58 | }
59 |
60 | public String poll(long timeout) {
61 |
62 | // Retrieve and remove the head of the loggerQueue, or return null if the dispatchQueue is empty
63 | try {
64 | return loggerQueue.poll(timeout, TimeUnit.SECONDS);
65 | } catch (InterruptedException e) {
66 | LOGGER.fine("Logger Queue poll interrupted.");
67 | }
68 | return null;
69 |
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/profiler/CPUTimer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.profiler;
18 |
19 | import java.lang.management.ManagementFactory;
20 | import java.lang.management.ThreadMXBean;
21 | import java.util.logging.Logger;
22 |
23 | import io.top4j.javaagent.mbeans.logger.StatsLogger;
24 |
25 | public class CPUTimer {
26 |
27 | private long lastCurrentTime;
28 | private long lastCPUTime;
29 | private ThreadMXBean threadMXBean;
30 |
31 | private static final Logger LOGGER = Logger.getLogger(StatsLogger.class.getName());
32 |
33 | public CPUTimer() {
34 |
35 | ThreadMXBean threadMXBean =
36 | ManagementFactory.getThreadMXBean();
37 | this.threadMXBean = threadMXBean;
38 |
39 | }
40 |
41 | /*
42 | * start CPU timer
43 | *
44 | */
45 | public void start() {
46 |
47 | // get current thread CPU time
48 | long cpuTime = threadMXBean.getCurrentThreadCpuTime();
49 |
50 | // store CPU time
51 | this.lastCPUTime = cpuTime;
52 |
53 | // get current system time
54 | long currentTime = System.nanoTime();
55 |
56 | // store system time
57 | this.lastCurrentTime = currentTime;
58 |
59 | }
60 |
61 | /*
62 | * stop CPU timer
63 | *
64 | */
65 | public void stop() {
66 |
67 | // get current thread CPU time
68 | long cpuTime = threadMXBean.getCurrentThreadCpuTime();
69 |
70 | // get current system time
71 | long currentTime = System.nanoTime();
72 |
73 | // calculate CPU burn in milliseconds
74 | long cpuBurn = cpuTime - lastCPUTime;
75 |
76 | // calculate elapsed time in milliseconds
77 | long elapsedTime = currentTime - lastCurrentTime;
78 |
79 | // log cpuBurn and elapsedTime
80 | LOGGER.info("CPU Burn = " + cpuBurn + " ns, Elapsed Time = " + elapsedTime + " ns");
81 |
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/profiler/CpuTime.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.profiler;
18 |
19 | import java.lang.management.ManagementFactory;
20 | import java.lang.management.ThreadMXBean;
21 |
22 | public class CpuTime {
23 |
24 | private long lastCPUTime;
25 | private ThreadMXBean threadMXBean;
26 |
27 | public CpuTime() {
28 |
29 | ThreadMXBean threadMXBean =
30 | ManagementFactory.getThreadMXBean();
31 | this.threadMXBean = threadMXBean;
32 | // initialise CPU time
33 | init();
34 |
35 | }
36 |
37 | /*
38 | * reset CPU time
39 | *
40 | */
41 | public void init() {
42 |
43 | // get and store current thread CPU time
44 | this.lastCPUTime = threadMXBean.getCurrentThreadCpuTime();
45 |
46 | }
47 |
48 | /*
49 | * get CPU time
50 | *
51 | */
52 | public long get() {
53 |
54 | // get current thread CPU time
55 | long cpuTime = threadMXBean.getCurrentThreadCpuTime();
56 |
57 | // calculate CPU burn in nanoseconds
58 | long cpuBurn = cpuTime - lastCPUTime;
59 |
60 | return cpuBurn;
61 |
62 | }
63 |
64 | /*
65 | * get CPU time in milliseconds
66 | *
67 | */
68 | public double getMillis() {
69 |
70 | // get current thread CPU time
71 | long cpuTime = threadMXBean.getCurrentThreadCpuTime();
72 |
73 | // calculate CPU burn in milliseconds
74 | double cpuBurn = ((double) cpuTime - lastCPUTime) / 1000000;
75 |
76 | return cpuBurn;
77 |
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/test/CollatorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.test;
18 |
19 | import java.util.NavigableMap;
20 | import java.util.Random;
21 | import java.util.TreeMap;
22 |
23 | public class CollatorTest {
24 |
25 | /**
26 | * Run collator test
27 | * @param args list of command-line arguments
28 | */
29 | public static void main(String[] args) {
30 |
31 | log("Running Collator Test....");
32 | NavigableMap sortedMap = new TreeMap();
33 | Random randomGenerator = new Random();
34 |
35 | for (int idx = 1; idx <= 10; ++idx) {
36 | int randomInt = randomGenerator.nextInt(100000);
37 | long randomLong = randomGenerator.nextLong();
38 | log("Generated : " + randomLong + " -> " + randomInt);
39 | sortedMap.put(randomLong, randomInt);
40 | }
41 |
42 | for (Long key : sortedMap.descendingKeySet()) {
43 | log(String.valueOf(key) + " -> " + sortedMap.get(key));
44 | }
45 |
46 | }
47 |
48 | private static void log(String aMessage) {
49 | System.out.println(aMessage);
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/test/MemTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.test;
18 |
19 | public class MemTest {
20 |
21 | static String DATA = "THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!! THIS IS A TEST STRING!!";
22 |
23 | /**
24 | * Run memory test
25 | * @param args list of command-line arguments
26 | */
27 | public static void main(String[] args) {
28 |
29 | System.out.println("Firing up JavaAgent memory test....");
30 |
31 | int iterations = 30000;
32 |
33 | for (int i = 0; i < iterations; i++) {
34 |
35 | churnMemory();
36 |
37 | try {
38 | Thread.sleep(1);
39 | } catch (InterruptedException e) {
40 | System.err.println("Thread sleep interrupted.");
41 | }
42 |
43 | }
44 |
45 | }
46 |
47 | public static void churnMemory() {
48 |
49 | StringBuilder sb = new StringBuilder();
50 | int iterations = 100;
51 |
52 | for (int i = 0; i < iterations; i++) {
53 |
54 | sb.append(DATA);
55 |
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/test/Test.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.test;
18 |
19 | public class Test {
20 |
21 | /**
22 | * Run JavaAgent test
23 | * @param args list of command-line arguments
24 | */
25 | public static void main(String[] args) {
26 | System.out.println("Firing up JavaAgent test....");
27 | try {
28 | Thread.sleep(300000);
29 | } catch (InterruptedException e) {
30 | System.err.println("Thread sleep interrupted.");
31 | }
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/utils/GarbageCollectorNames.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.utils;
18 |
19 | import io.top4j.javaagent.mbeans.jvm.gc.GarbageCollectorMXBeanHelper;
20 |
21 | import javax.management.MBeanServer;
22 | import java.lang.management.ManagementFactory;
23 | import java.util.List;
24 |
25 | public class GarbageCollectorNames {
26 |
27 | public static void main(String[] args) {
28 |
29 | // list garbage collector names
30 | list();
31 | }
32 |
33 | private static void list() {
34 |
35 | // get platform MBean server
36 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
37 |
38 | // instantiate new GarbageCollectorMXBeanHelper
39 | GarbageCollectorMXBeanHelper gcMxBeanHelper = null;
40 | try {
41 | gcMxBeanHelper = new GarbageCollectorMXBeanHelper(mbs);
42 | } catch (Exception e) {
43 | System.err.println("ERROR: Unable to initialise GarbageCollectorMXBeanHelper due to : " + e.getMessage());
44 | }
45 |
46 | // get list of garbage collector names
47 | List gcNames = gcMxBeanHelper.listGarbageCollectorNames();
48 |
49 | System.out.println("JVM Garbage Collector Names");
50 | System.out.println("===========================");
51 | for (String gcName : gcNames) {
52 |
53 | // print mpName to stdout
54 | System.out.println(gcName);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/utils/MBeanInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.utils;
18 |
19 | import java.util.Collection;
20 |
21 | import javax.management.ObjectName;
22 |
23 | public class MBeanInfo {
24 |
25 | private ObjectName objectName;
26 | private String keyPropertyList;
27 | private Collection attributeNames;
28 | private String statsType;
29 |
30 | public ObjectName getObjectName() {
31 | return objectName;
32 | }
33 |
34 | public void setObjectName(ObjectName objectName) {
35 | this.objectName = objectName;
36 | }
37 |
38 | public String getKeyPropertyList() {
39 | return keyPropertyList;
40 | }
41 |
42 | public void setKeyPropertyList(String keyPropertyList) {
43 | this.keyPropertyList = keyPropertyList;
44 | }
45 |
46 | public Collection getAttributeNames() {
47 | return attributeNames;
48 | }
49 |
50 | public void setAttributeNames(Collection attributeNames) {
51 | this.attributeNames = attributeNames;
52 | }
53 |
54 | public String getStatsType() {
55 | return statsType;
56 | }
57 |
58 | public void setStatsType(String statsType) {
59 | this.statsType = statsType;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/main/java/io/top4j/javaagent/utils/MemoryPoolNames.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.top4j.javaagent.utils;
18 |
19 | import io.top4j.javaagent.mbeans.jvm.memory.MemoryPoolMXBeanHelper;
20 |
21 | import javax.management.MBeanServer;
22 | import java.lang.management.ManagementFactory;
23 | import java.util.List;
24 |
25 | public class MemoryPoolNames {
26 |
27 | public static void main(String[] args) {
28 |
29 | // list memory pool names
30 | list();
31 | }
32 |
33 | private static void list() {
34 |
35 | // get platform MBean server
36 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
37 |
38 | // instantiate new MemoryPoolMXBeanHelper
39 | MemoryPoolMXBeanHelper memoryPoolMxBeanHelper = null;
40 | try {
41 | memoryPoolMxBeanHelper = new MemoryPoolMXBeanHelper(mbs);
42 | } catch (Exception e) {
43 | System.err.println("ERROR: Unable to initialise MemoryPoolMXBeanHelper due to : " + e.getMessage());
44 | }
45 |
46 | // get list of memory pool names
47 | List memoryPoolNames = memoryPoolMxBeanHelper.listMemoryPoolNames();
48 |
49 | System.out.println("JVM Memory Pool Names");
50 | System.out.println("=====================");
51 | for (String mpName : memoryPoolNames) {
52 |
53 | // print mpName to stdout
54 | System.out.println(mpName);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/java/JunitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Open Answers Ltd. https://www.openanswers.co.uk
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import org.junit.Test;
18 |
19 | import static org.junit.Assert.assertEquals;
20 |
21 | public class JunitTest {
22 | @Test
23 | public void testJunit() {
24 | String str = "Junit is working fine";
25 | assertEquals("Junit is working fine", str);
26 | System.out.println("JUnit test complete.");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/resources/assertion-data.csv:
--------------------------------------------------------------------------------
1 | #
2 | # assertion-data.csv
3 | #
4 | # Fields:
5 | #
6 | # 1. StatsType - the Top4J stats type
7 | # 2. Attribute - the Top4J MBean attribute name
8 | # 3. Comparator - the assertion comparator, where gt = greater than, ge = greater than or equal to, lt = less than, le = less than or equal to, eq = equal to
9 | # 4. AssertionType - the data type of the assertion data
10 | # 5. AssertionData - the assertion data
11 | #
12 | GCStats,GcOverhead,gt,double,0.0
13 | GCStats,MeanNurseryGCTime,gt,double,0.1
14 | GCStats,MeanTenuredGCTime,eq,double,0.0
15 | #GCStats,MBeanCpuTime,gt,double,0.1
16 | MemoryStats,MemoryAllocationRate,gt,double,1.0
17 | MemoryStats,MemoryPromotionRate,ge,double,0.0
18 | MemoryStats,MemorySurvivorRate,gt,double,0.0
19 | #MemoryStats,MBeanCpuTime,gt,double,1.0
20 | HeapStats,EdenSpaceUtil,eq,double,0.0
21 | HeapStats,SurvivorSpaceUtil,gt,double,0.1
22 | HeapStats,TenuredHeapUtil,eq,double,0.0
23 | #HeapStats,MBeanCpuTime,gt,double,0.1
24 | AgentStats,AgentCpuUtil,gt,double,0.0
25 | AgentStats,AgentCpuTime,gt,double,10.0
26 | AgentStats,Iterations,gt,long,0
27 | #AgentStats,MBeanCpuTime,gt,double,0.1
28 | ThreadStats,CpuUsage,gt,double,0.0
29 | ThreadStats,UserCpuUsage,gt,double,0.0
30 | ThreadStats,SysCpuUsage,ge,double,0.0
31 | ThreadStats,ThreadCount,gt,long,10
32 | ThreadStats,RunnableThreadCount,gt,long,1
33 | ThreadStats,BlockedThreadCount,gt,long,1
34 | ThreadStats,WaitingThreadCount,gt,long,1
35 | ThreadStats,TimedWaitingThreadCount,gt,long,0
36 | ThreadStats,MBeanCpuTime,gt,double,10.0
37 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/jmapCollector.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # jmapCollector.sh
4 | #
5 | # - collect jmap heap dumps at regular intervals
6 | #
7 |
8 | JVM_PID=$1
9 | JMAP_COMMAND="jmap -histo:live"
10 | INTERVAL=600
11 |
12 | # check args
13 | if [[ ! ${JVM_PID} =~ [0-9]+ ]]
14 | then
15 | echo "USAGE: $0 "
16 | exit 1
17 | fi
18 |
19 | # check JVM_PID is running
20 | if ! `ps -p ${JVM_PID} | grep -q java`
21 | then
22 | echo "ERROR: Unable to find JVM process with PID ${JVM_PID}"
23 | exit 2
24 | fi
25 |
26 | echo "Running jmap heap dumps against JVM PID ${JVM_PID}...."
27 | ps -fp ${JVM_PID}
28 |
29 | i=1
30 |
31 | while true
32 | do
33 | echo "Taking JVM PID ${JVM_PID} heap dump @ `date`"
34 | ${JMAP_COMMAND} ${JVM_PID} > jmap.${JVM_PID}-${i}.txt
35 | if [[ $? -gt 0 ]]
36 | then
37 | echo "ERROR: Problem running jmap command....exiting"
38 | exit 3
39 | fi
40 | (( i=i+1 ))
41 | sleep ${INTERVAL}
42 | done
43 |
44 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/listGarbageCollectorNames.sh:
--------------------------------------------------------------------------------
1 | . `dirname $0`/setenv.sh
2 | java -classpath "../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar" ${JAVA_OPTS} $@ io.top4j.javaagent.utils.GarbageCollectorNames
3 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/listMemoryPoolNames.sh:
--------------------------------------------------------------------------------
1 | . `dirname $0`/setenv.sh
2 | java -classpath "../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar" ${JAVA_OPTS} $@ io.top4j.javaagent.utils.MemoryPoolNames
3 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/logging.properties:
--------------------------------------------------------------------------------
1 | ############################################################
2 | # Default Logging Configuration File
3 | #
4 | # You can use a different file by specifying a filename
5 | # with the java.util.logging.config.file system property.
6 | # For example java -Djava.util.logging.config.file=myfile
7 | ############################################################
8 |
9 | ############################################################
10 | # Global properties
11 | ############################################################
12 |
13 | # "handlers" specifies a comma separated list of log Handler
14 | # classes. These handlers will be installed during VM startup.
15 | # Note that these classes must be on the system classpath.
16 | # By default we only configure a ConsoleHandler, which will only
17 | # show messages at the INFO and above levels.
18 | handlers= java.util.logging.ConsoleHandler
19 |
20 | # To also add the FileHandler, use the following line instead.
21 | #handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
22 |
23 | # Default global logging level.
24 | # This specifies which kinds of events are logged across
25 | # all loggers. For any given facility this global level
26 | # can be overriden by a facility specific level
27 | # Note that the ConsoleHandler also has a separate level
28 | # setting to limit messages printed to the console.
29 | .level= INFO
30 |
31 | ############################################################
32 | # Handler specific properties.
33 | # Describes specific configuration info for Handlers.
34 | ############################################################
35 |
36 | # default file output is in user's home directory.
37 | java.util.logging.FileHandler.pattern = %h/java%u.log
38 | java.util.logging.FileHandler.limit = 50000
39 | java.util.logging.FileHandler.count = 1
40 | java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
41 |
42 | # Limit the message that are printed on the console to INFO and above.
43 | java.util.logging.ConsoleHandler.level = INFO
44 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
45 |
46 | # Example to customize the SimpleFormatter output format
47 | # to print one-line log message like this:
48 | # : []
49 | #
50 | # java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
51 | java.util.logging.SimpleFormatter.format=%4$s %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS Top4J JavaAgent: %5$s%6$s%n
52 |
53 | ############################################################
54 | # Facility specific properties.
55 | # Provides extra control for each logger.
56 | ############################################################
57 |
58 | # For example, set the com.xyz.foo logger to only log SEVERE
59 | # messages:
60 | com.xyz.foo.level = SEVERE
61 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runCollatorTest.sh:
--------------------------------------------------------------------------------
1 | java -classpath "../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar" io.top4j.javaagent.test.CollatorTest
2 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMTCMSTest.sh:
--------------------------------------------------------------------------------
1 | export JAVA_OPTS="-XX:+UseConcMarkSweepGC -Xms6m -Xmx6m -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -verbosegc"
2 | `dirname $0`/runMultiThreadedTest.sh $*
3 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMTG1Test.sh:
--------------------------------------------------------------------------------
1 | export JAVA_OPTS="-XX:+UseG1GC -Xms4m -Xmx4m -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -verbosegc"
2 | `dirname $0`/runMultiThreadedTest.sh $*
3 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMemReport.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 | #
3 | # runMemReport.sh
4 | #
5 |
6 | HEAP_SIZE=$1
7 |
8 | if [[ -z $HEAP_SIZE ]]
9 | then
10 | HEAP_SIZE=128
11 | fi
12 |
13 | RUN_MEM_TEST=`dirname $0`/runMemTest.sh
14 |
15 | # run mem test
16 |
17 | ${RUN_MEM_TEST} ${HEAP_SIZE} 2>&1 | \
18 |
19 | egrep " Rate|GC Overhead|GC Time" | \
20 |
21 | gawk ' {
22 |
23 | if ($0 ~ /GC Overhead/) {
24 |
25 | gsub("%", "")
26 | total["gcOverhead"]+=$9
27 | count["gcOverhead"]++
28 |
29 | }
30 |
31 | if ($0 ~ /Memory Allocation Rate/) {
32 |
33 | total["memAllocRate"]+=$10
34 | count["memAllocRate"]++
35 |
36 | }
37 |
38 | if ($0 ~ /Memory Survivor Rate/) {
39 |
40 | total["memSurvivorRate"]+=$10
41 | count["memSurvivorRate"]++
42 |
43 | }
44 |
45 | if ($0 ~ /Memory Promotion Rate/) {
46 |
47 | total["memPromoRate"]+=$10
48 | count["memPromoRate"]++
49 |
50 | }
51 |
52 | if ($0 ~ /Mean Nursery GC Time/) {
53 |
54 | gsub("ms", "")
55 | total["yGCTime"]+=$11
56 | count["yGCTime"]++
57 |
58 | }
59 |
60 | if ($0 ~ /Mean Tenured GC Time/) {
61 |
62 | gsub("ms", "")
63 | total["oGCTime"]+=$11
64 | count["oGCTime"]++
65 |
66 | }
67 |
68 |
69 | }
70 |
71 | END {
72 |
73 | #print "Mean GC Overhead = " total["gcOverhead"]/count["gcOverhead"] "%"
74 | #print "Mean Memory Allocation Rate = " total["memAllocRate"]/count["memAllocRate"] " MB/s"
75 | #print "Mean Survivor Survivor Rate = " total["memSurvivorRate"]/count["memSurvivorRate"] " MB/s"
76 | #print "Mean Survivor Promotion Rate = " total["memPromoRate"]/count["memPromoRate"] " MB/s"
77 |
78 | meanGCOverhead=total["gcOverhead"]/count["gcOverhead"]
79 | meanMemAllocRate=total["memAllocRate"]/count["memAllocRate"]
80 | meanMemSurvivorRate=total["memSurvivorRate"]/count["memSurvivorRate"]
81 | meanMemPromoRate=total["memPromoRate"]/count["memPromoRate"]
82 | meanYGCTime=total["yGCTime"]/count["yGCTime"]
83 | meanOGCTime=total["oGCTime"]/count["oGCTime"]
84 |
85 | print "Mean Memory Allocation Rate, Mean Survivor Survivor Rate, Mean Survivor Promotion Rate, Mean GC Overhead, Mean Nursery GC Time, Mean Tenured GC Time"
86 | print meanMemAllocRate "," meanMemSurvivorRate "," meanMemPromoRate "," meanGCOverhead "," meanYGCTime "," meanOGCTime
87 |
88 | } '
89 |
90 | exit
91 |
92 | INFO 2014-03-14 21:41:30 Top4J JavaAgent: GC Overhead = 2.6812313803376364%
93 | INFO 2014-03-14 21:41:30 Top4J JavaAgent: Mean Nursery GC Time = 9.0ms
94 | INFO 2014-03-14 21:41:30 Top4J JavaAgent: Mean Tenured GC Time = 0.0ms
95 | INFO 2014-03-14 21:41:31 Top4J JavaAgent: Memory Allocation Rate = 4544.242048216198 MB/s
96 | INFO 2014-03-14 21:41:31 Top4J JavaAgent: Memory Survivor Rate = 14.399205561072494 MB/s
97 | INFO 2014-03-14 21:41:31 Top4J JavaAgent: Memory Promotion Rate = 29.830281050226542 MB/s
98 |
99 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMemTest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # runMemTest.sh
4 | #
5 |
6 | HEAP_SIZE=$1
7 |
8 | if [[ -z $HEAP_SIZE ]]
9 | then
10 | HEAP_SIZE=128
11 | fi
12 |
13 | java -Xms${HEAP_SIZE}m -Xmx${HEAP_SIZE}m -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -verbosegc -Djava.util.logging.config.file=logging.properties -Dcom.sun.management.jmxremote -javaagent:../../../target/top4j-javaagent-0.0.9-SNAPSHOT.jar io.top4j.javaagent.test.MemTest
14 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMultiThreadedTest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # runMultiThreadedTest.sh
4 | #
5 | # - run Top4J multi-threaded test harness
6 | #
7 | # Arguments:
8 | #
9 | # 1. NUM_THREADS: Number of threads, e.g. 10
10 | # 2. NUM_ITERATIONS: Number of iterations per thread, e.g. 100
11 | # 3. PAUSE_TIME: Pause time between iterations in milliseconds, e.g. 10
12 | #
13 | # Example Usage:
14 | #
15 | # ./runMultiThreadedTest.sh 10 100 10
16 | #
17 |
18 | TOP4J_JAVAAGENT_JAR=`ls -1rt ../../../target/top4j-javaagent-*.jar | tail -1`
19 | ARG_COUNT=$#
20 | NUM_THREADS=$1
21 | NUM_ITERATIONS=$2
22 | PAUSE_TIME=$3
23 | SYNCHRONISED=$4
24 |
25 | if [[ ! -f ${TOP4J_JAVAAGENT_JAR} ]]
26 | then
27 | echo "ERROR: Unable to find Top4J java agent jar."
28 | echo "HINT: Try building the top4j-javaagent Maven project via \"mvn clean package\""
29 | exit 1
30 | fi
31 |
32 | if [[ ${ARG_COUNT} -ne 3 ]] && [[ ${ARG_COUNT} -ne 4 ]]
33 | then
34 | echo "USAGE: [synchronised]"
35 | exit 1
36 | fi
37 |
38 | java -classpath "${TOP4J_JAVAAGENT_JAR}" -javaagent:${TOP4J_JAVAAGENT_JAR}=test.property=test,top.thread.count=10 -Djava.util.logging.config.file=logging.properties ${JAVA_OPTS} io.top4j.javaagent.test.MultiThreadedTest ${NUM_THREADS} ${NUM_ITERATIONS} ${PAUSE_TIME} ${SYNCHRONISED}
39 |
40 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runMultiThreadedTestNoAgent.sh:
--------------------------------------------------------------------------------
1 | java -classpath "../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar" -Djava.util.logging.config.file=logging.properties ${JAVA_OPTS} io.top4j.javaagent.test.MultiThreadedTest $*
2 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/runSoakTest.sh:
--------------------------------------------------------------------------------
1 | java -classpath "../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar" -javaagent:../../../target/top4j-javaagent-0.0.1-SNAPSHOT.jar=top.thread.count=10,blocked.thread.count=10,collector.poll.frequency=1000 -Djava.util.logging.config.file=logging.properties ${JAVA_OPTS} io.top4j.javaagent.test.MultiThreadedTest 1000 350 10000
2 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/setenv.sh:
--------------------------------------------------------------------------------
1 | # use G1 garbage collector
2 | #export JAVA_OPTS="${JAVA_OPTS} -XX:+UseG1GC"
3 | # use concurrent mark and sweep collecor
4 | #export JAVA_OPTS="${JAVA_OPTS} -XX:+UseConcMarkSweepGC"
5 |
--------------------------------------------------------------------------------
/top4j-javaagent/src/test/scripts/top4j.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Top4J configuration file
3 | #
4 | collector.poll.frequency=3000
5 | stats.logger.poll.timeout=600
6 | stats.logger.enabled=true
7 | # stats.logger.format:
8 | # csv or console
9 | stats.logger.format=csv
10 | # stats log directory
11 | stats.logger.directory=top4j-stats
12 | # stats logger log file name date stamp format - the datestamp that appears within the stats log file name
13 | stats.logger.log.file.name.date.format=yyyyMMdd
14 | # stats logger date stamp format
15 | stats.logger.date.format=yyyy-MM-dd'T'HH:mm:ss.SSSZ
16 | # stats logger field separator
17 | stats.logger.field.separator=,
18 | # use this logger.format for debugging
19 | #logger.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s: %5$s%6$s%n
20 | # use this logger.format for production
21 | logger.format=%4$s %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS Top4J JavaAgent: %5$s%6$s%n
22 | # top thread count - the number of top threads to track via TopThreads MBean
23 | top.thread.count=5
24 | # top threads stack trace logging on/off switch
25 | top.threads.stack.trace.logging.enabled=true
26 | # top threads stack trace CPU util threshold
27 | # - log stack trace if CPU util threshold exceeded
28 | top.threads.stack.trace.cpu.threshold=1
29 | # the number of top thread stack frames to log
30 | top.threads.stack.trace.frames=10
31 | # thread contention monitoring on/off switch
32 | thread.contention.monitoring.enabled=true
33 | # blocked thread count - the number of blocked threads to track via BlockedThreads MBean
34 | blocked.thread.count=10
35 | # blocked threads stack trace logging on/off switch
36 | blocked.threads.stack.trace.logging.enabled=true
37 | # blocked threads stack trace blocked percentage threshold
38 | # - log stack trace if blocked percentage threshold exceeded
39 | blocked.threads.stack.trace.blocked.percentage.threshold=10
40 | # the number of blocked thread stack frames to log
41 | blocked.threads.stack.trace.frames=10
42 | # hot method profiling on/off switch
43 | hot.method.profiling.enabled=false
44 | # hot method profiler poll frequency in ms
45 | hot.method.poll.frequency=10
46 |
--------------------------------------------------------------------------------
/top4j-javaagent/top4j-javaagent.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/top4j-parent.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------