Skip to content

Commit 29e12fe

Browse files
committed
[agent.java] support java 20, support virtual thread
1 parent c47e0ad commit 29e12fe

File tree

9 files changed

+235
-175
lines changed

9 files changed

+235
-175
lines changed

pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<module>scouter.agent.host</module>
2323
<module>scouter.agent.java</module>
2424
<module>scouter.agent.batch</module>
25+
<module>scouter.extra.java20</module>
2526
</modules>
2627

2728
<properties>
@@ -176,7 +177,7 @@
176177
<plugin>
177178
<groupId>org.apache.maven.plugins</groupId>
178179
<artifactId>maven-javadoc-plugin</artifactId>
179-
<version>3.2.0</version>
180+
<version>3.5.0</version>
180181
</plugin>
181182
<plugin>
182183
<groupId>org.sonatype.plugins</groupId>

scouter.agent.java/pom.xml

Lines changed: 15 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,18 @@
3737
<compilerVersion>1.8</compilerVersion>
3838
<source>1.8</source>
3939
<target>1.8</target>
40+
<fork>true</fork>
41+
<executable>${JAVA_20_HOME}/bin/javac</executable>
4042
</configuration>
4143
</plugin>
44+
<plugin>
45+
<groupId>org.apache.maven.plugins</groupId>
46+
<artifactId>maven-javadoc-plugin</artifactId>
47+
<configuration>
48+
<javadocExecutable>${JAVA_20_HOME}/bin/javadoc</javadocExecutable>
49+
</configuration>
50+
<version>3.5.0</version>
51+
</plugin>
4252
<plugin>
4353
<groupId>org.apache.maven.plugins</groupId>
4454
<artifactId>maven-antrun-plugin</artifactId>
@@ -199,155 +209,6 @@
199209
</plugins>
200210
</build>
201211
</profile>
202-
<profile>
203-
<id>java-legacy</id>
204-
<properties>
205-
<env>java-legacy</env>
206-
</properties>
207-
<dependencies>
208-
<dependency>
209-
<groupId>org.javassist</groupId>
210-
<artifactId>javassist</artifactId>
211-
<version>3.21.0-GA</version>
212-
</dependency>
213-
</dependencies>
214-
<build>
215-
<plugins>
216-
<plugin>
217-
<groupId>org.apache.maven.plugins</groupId>
218-
<artifactId>maven-compiler-plugin</artifactId>
219-
<version>3.1</version>
220-
<configuration>
221-
<compilerVersion>1.6</compilerVersion>
222-
<source>1.6</source>
223-
<target>1.6</target>
224-
<excludes>
225-
<exclude>scouter/xtra/reactive/*.java</exclude>
226-
<exclude>scouter/xtra/java8/*.java</exclude>
227-
<exclude>reactor/**/*.java</exclude>
228-
<exclude>com/**/*.java</exclude>
229-
</excludes>
230-
</configuration>
231-
</plugin>
232-
<plugin>
233-
<groupId>org.apache.maven.plugins</groupId>
234-
<artifactId>maven-antrun-plugin</artifactId>
235-
<version>1.8</version>
236-
<executions>
237-
<execution>
238-
<id>make-ext-jar</id>
239-
<phase>package</phase>
240-
<configuration>
241-
<target>
242-
<jar destfile="${project.build.directory}/${scouter.http.jar}">
243-
<fileset dir="${project.build.outputDirectory}">
244-
<include name="scouter/xtra/http/*.class" />
245-
</fileset>
246-
</jar>
247-
<jar destfile="${project.build.directory}/${scouter.jdbc.jar}">
248-
<fileset dir="${project.build.outputDirectory}">
249-
<include name="scouter/xtra/jdbc/*.class" />
250-
</fileset>
251-
</jar>
252-
<jar destfile="${project.build.directory}/${scouter.httpclient.jar}">
253-
<fileset dir="${project.build.outputDirectory}">
254-
<include name="scouter/xtra/httpclient/*.class" />
255-
</fileset>
256-
</jar>
257-
<jar destfile="${project.build.directory}/${scouter.tools.jar}">
258-
<fileset dir="${project.build.outputDirectory}">
259-
<include name="scouter/xtra/tools/*.class" />
260-
</fileset>
261-
</jar>
262-
<jar destfile="${project.build.directory}/${scouter.kafka.jar}">
263-
<fileset dir="${project.build.outputDirectory}">
264-
<include name="scouter/xtra/kafka/*.class" />
265-
</fileset>
266-
</jar>
267-
<jar destfile="${project.build.directory}/${scouter.redis.jar}">
268-
<fileset dir="${project.build.outputDirectory}">
269-
<include name="scouter/xtra/redis/*.class" />
270-
</fileset>
271-
</jar>
272-
</target>
273-
</configuration>
274-
<goals>
275-
<goal>run</goal>
276-
</goals>
277-
</execution>
278-
<execution>
279-
<id>add-to-uber-jar</id>
280-
<phase>package</phase>
281-
<configuration>
282-
<target>
283-
<echo message="final.jar.name = ${final.jar.name}" />
284-
<echo message="final.jar.name.xtra = ${final.jar.name.xtra}" />
285-
286-
<jar destfile="${final.jar.name.xtra}">
287-
<fileset dir="${project.build.directory}">
288-
<include name="${scouter.http.jar}" />
289-
<include name="${scouter.jdbc.jar}" />
290-
<include name="${scouter.httpclient.jar}" />
291-
<include name="${scouter.tools.jar}" />
292-
<include name="${scouter.kafka.jar}" />
293-
<include name="${scouter.redis.jar}" />
294-
</fileset>
295-
<zipfileset src="${final.jar.name}" />
296-
297-
<manifest>
298-
<attribute name="Premain-Class" value="scouter.agent.JavaAgent" />
299-
<attribute name="Agent-Class" value="scouter.agent.JavaAgent" />
300-
<attribute name="Can-Redefine-Classes" value="true" />
301-
<attribute name="Can-Retransform-Classes" value="true" />
302-
<attribute name="Boot-Class-Path" value="${project.build.finalName}.jar" />
303-
</manifest>
304-
</jar>
305-
306-
<copy file="${final.jar.name}" tofile="${final.jar.name.shade}" overwrite="true" verbose="true" />
307-
<copy file="${final.jar.name.xtra}" tofile="${final.jar.name}" overwrite="true" verbose="true" />
308-
<delete file="${project.build.directory}/${scouter.http.jar}" />
309-
<delete file="${project.build.directory}/${scouter.jdbc.jar}" />
310-
<delete file="${project.build.directory}/${scouter.httpclient.jar}" />
311-
<delete file="${project.build.directory}/${scouter.tools.jar}" />
312-
<delete file="${project.build.directory}/${scouter.kafka.jar}" />
313-
<delete file="${project.build.directory}/${scouter.redis.jar}" />
314-
315-
<!-- for constant name file -->
316-
<jar destfile="${project.build.directory}/${scouter.agent.file.name}">
317-
<zipfileset src="${final.jar.name}" />
318-
<manifest>
319-
<attribute name="Premain-Class" value="scouter.agent.JavaAgent" />
320-
<attribute name="Agent-Class" value="scouter.agent.JavaAgent" />
321-
<attribute name="Can-Redefine-Classes" value="true" />
322-
<attribute name="Can-Retransform-Classes" value="true" />
323-
<attribute name="Boot-Class-Path" value="${scouter.agent.file.name}" />
324-
</manifest>
325-
</jar>
326-
</target>
327-
</configuration>
328-
<goals>
329-
<goal>run</goal>
330-
</goals>
331-
</execution>
332-
<execution>
333-
<id>make-assembly</id>
334-
<phase>package</phase>
335-
<configuration>
336-
<target>
337-
<mkdir dir="${scouter.whole.packaging.prepare.dir}" />
338-
<mkdir dir="${scouter.whole.packaging.prepare.dir}/${scouter.agent.java.legacy.dir.name}" />
339-
<copy file="${project.build.directory}/${scouter.agent.file.name}" todir="${scouter.whole.packaging.prepare.dir}/${scouter.agent.java.legacy.dir.name}" />
340-
</target>
341-
</configuration>
342-
<goals>
343-
<goal>run</goal>
344-
</goals>
345-
</execution>
346-
</executions>
347-
</plugin>
348-
</plugins>
349-
</build>
350-
</profile>
351212
</profiles>
352213

353214
<properties>
@@ -376,6 +237,11 @@
376237
</properties>
377238

378239
<dependencies>
240+
<dependency>
241+
<groupId>io.github.scouter-project</groupId>
242+
<artifactId>scouter-extra-java20</artifactId>
243+
<version>${project.version}</version>
244+
</dependency>
379245
<dependency>
380246
<groupId>io.github.scouter-project</groupId>
381247
<artifactId>scouter-common</artifactId>

scouter.agent.java/src/main/java/scouter/agent/Configure.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ public static final Configure getInstance() {
297297
public File plugin_dir = new File(agent_dir_path + "/plugin");
298298
@ConfigDesc("Dump directory")
299299
public File dump_dir = new File(agent_dir_path + "/dump");
300+
@ConfigDesc("Thread dump json format - only for virtual thread")
301+
public boolean thread_dump_json_format = false;
300302
//public File mgr_agent_lib_dir = new File("./_scouter_");
301303
@ConfigDesc("Script plugin enabled")
302304
public boolean plugin_enabled = true;
@@ -960,6 +962,7 @@ private void apply() {
960962
this.trace_service_name_get_key = getValue("trace_service_name_get_key");
961963
this.trace_service_name_post_key = getValue("trace_service_name_post_key");
962964
this.dump_dir = new File(getValue("dump_dir", agent_dir_path + "/dump"));
965+
this.thread_dump_json_format = getBoolean("thread_dump_json_format", false);
963966
try {
964967
this.dump_dir.mkdirs();
965968
} catch (Exception e) {

scouter.agent.java/src/main/java/scouter/agent/counter/task/MakeStack.java

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import scouter.agent.trace.TraceMain;
1212
import scouter.lang.pack.StackPack;
1313
import scouter.lang.step.DumpStep;
14+
import scouter.util.StringUtil;
1415

1516
import java.io.PrintWriter;
1617
import java.io.StringWriter;
@@ -119,27 +120,47 @@ private void stepDump(ThreadMXBean tmxBean, TraceContext ctx) {
119120
}
120121

121122
ThreadInfo tInfo = tmxBean.getThreadInfo(ctx.threadId, 50);
122-
if (tInfo == null) return;
123+
if (tInfo != null) {
124+
StackTraceElement[] elements = tInfo.getStackTrace();
125+
int length = elements.length;
126+
int[] stacks = new int[length];
123127

124-
StackTraceElement[] elements = tInfo.getStackTrace();
125-
int length = elements.length;
126-
int[] stacks = new int[length];
127-
128-
for (int i = 0; i < length; i++) {
129-
stacks[i] = DataProxy.sendStackElement(elements[i]);
128+
for (int i = 0; i < length; i++) {
129+
stacks[i] = DataProxy.sendStackElement(elements[i]);
130+
}
131+
DumpStep dumpStep = new DumpStep();
132+
dumpStep.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
133+
dumpStep.stacks = stacks;
134+
dumpStep.threadId = ctx.threadId;
135+
dumpStep.threadName = tInfo.getThreadName();
136+
dumpStep.threadState = tInfo.getThreadState().toString();
137+
dumpStep.lockOwnerId = tInfo.getLockOwnerId();
138+
dumpStep.lockName = tInfo.getLockName();
139+
dumpStep.lockOwnerName = tInfo.getLockOwnerName();
140+
141+
ctx.temporaryDumpSteps.offer(dumpStep);
142+
ctx.hasDumpStack = true;
143+
} else {
144+
Thread t = ctx.thread;
145+
if (t != null) {
146+
StackTraceElement[] elements = t.getStackTrace();
147+
int length = Math.min(elements.length, 50);
148+
int[] stacks = new int[length];
149+
150+
for (int i = 0; i < length; i++) {
151+
stacks[i] = DataProxy.sendStackElement(elements[i]);
152+
}
153+
DumpStep dumpStep = new DumpStep();
154+
dumpStep.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
155+
dumpStep.stacks = stacks;
156+
dumpStep.threadId = ctx.threadId;
157+
dumpStep.threadName = StringUtil.isEmpty(t.getName()) ? t.toString() : t.getName();
158+
dumpStep.threadState = t.getState().name();
159+
160+
ctx.temporaryDumpSteps.offer(dumpStep);
161+
ctx.hasDumpStack = true;
162+
}
130163
}
131-
DumpStep dumpStep = new DumpStep();
132-
dumpStep.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
133-
dumpStep.stacks = stacks;
134-
dumpStep.threadId = ctx.threadId;
135-
dumpStep.threadName = tInfo.getThreadName();
136-
dumpStep.threadState = tInfo.getThreadState().toString();
137-
dumpStep.lockOwnerId = tInfo.getLockOwnerId();
138-
dumpStep.lockName = tInfo.getLockName();
139-
dumpStep.lockOwnerName = tInfo.getLockOwnerName();
140-
141-
ctx.temporaryDumpSteps.offer(dumpStep);
142-
ctx.hasDumpStack = true;
143164
}
144165

145166
private void reactiveStepDump(ThreadMXBean tmxBean, TraceContext ctx) {

scouter.agent.java/src/main/java/scouter/agent/netio/request/handle/AgentThread.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
import scouter.util.*;
3737

3838
import java.io.IOException;
39+
import java.lang.management.ManagementFactory;
40+
import java.lang.management.ThreadInfo;
41+
import java.lang.management.ThreadMXBean;
3942
import java.util.Enumeration;
4043
import java.util.Map;
4144

@@ -78,7 +81,35 @@ public Pack threadDetail(Pack param) {
7881
}
7982

8083
if(threadId != 0L) {
81-
p = ThreadUtil.appendThreadDetail(threadId, p);
84+
ThreadMXBean tmb = ManagementFactory.getThreadMXBean();
85+
ThreadInfo f = tmb.getThreadInfo(threadId, 500);
86+
if (f == null) {
87+
Thread t = ctx.thread;
88+
if (t != null) {
89+
p.put("Thread Id", new DecimalValue(t.getId()));
90+
p.put("State", new TextValue(t.getState().name()));
91+
String name = t.getName();
92+
if (StringUtil.isEmpty(name)) {
93+
name = t.toString();
94+
}
95+
p.put("Thread Name", new TextValue(name));
96+
p.put("Stack Trace", new TextValue(ThreadUtil.getStackTrace(t.getStackTrace())));
97+
}
98+
} else {
99+
p.put("Thread Id", new DecimalValue(f.getThreadId()));
100+
p.put("Thread Cpu Time", new DecimalValue(tmb.getThreadCpuTime(threadId) / 1000000));
101+
p.put("Thread User Time", new DecimalValue(tmb.getThreadUserTime(threadId) / 1000000));
102+
p.put("Blocked Count", new DecimalValue(f.getBlockedCount()));
103+
p.put("Blocked Time", new DecimalValue(f.getBlockedTime()));
104+
p.put("Waited Count", new DecimalValue(f.getWaitedCount()));
105+
p.put("Waited Time", new DecimalValue(f.getWaitedTime()));
106+
p.put("Lock Owner Id", new DecimalValue(f.getLockOwnerId()));
107+
p.put("Lock Name", new TextValue(f.getLockName()));
108+
p.put("Lock Owner Name", new TextValue(f.getLockOwnerName()));
109+
p.put("Thread Name", new TextValue(f.getThreadName()));
110+
p.put("Stack Trace", new TextValue(ThreadUtil.getStackTrace(f.getStackTrace())));
111+
p.put("State", new TextValue(f.getThreadState().toString()));
112+
}
82113

83114
} else {
84115
TraceContext deferredContext = TraceContextManager.getDeferredContext(txid);

0 commit comments

Comments
 (0)