vmtool command support interrupt thread. #2427

This commit is contained in:
GGGGGHT 2023-04-19 19:24:00 +08:00 committed by hengyunabc
parent 929adc8c9d
commit 735ec2e0b5
4 changed files with 63 additions and 2 deletions

View File

@ -1,5 +1,7 @@
package arthas;
import java.util.Map;
/**
* @author ZhangZiCheng 2021-02-12
* @author hengyunabc 2021-04-26
@ -70,6 +72,17 @@ public class VmTool implements VmToolMXBean {
forceGc0();
}
@Override
public void interruptSpecialThread(int threadId) {
Map<Thread, StackTraceElement[]> allThread = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> entry : allThread.entrySet()) {
if (entry.getKey().getId() == threadId) {
entry.getKey().interrupt();
return;
}
}
}
@Override
public <T> T[] getInstances(Class<T> klass) {
return getInstances0(klass, -1);

View File

@ -20,6 +20,13 @@ public interface VmToolMXBean {
*/
public void forceGc();
/**
* 打断指定线程
*
* @param threadId 线程ID
*/
void interruptSpecialThread(int threadId);
public <T> T[] getInstances(Class<T> klass);
/**

View File

@ -3,9 +3,11 @@ package arthas;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Test;
import com.taobao.arthas.common.VmToolUtils;
@ -182,4 +184,30 @@ public class VmToolTest {
Assertions.assertThat(interfaceInstances[0]).isEqualTo(ObjectInstances[0]);
}
@Test
public void test_interrupt_thread() throws InterruptedException {
String threadName = "interruptMe";
final RuntimeException[] re = new RuntimeException[1];
Runnable runnable = new Runnable() {
@Override public void run() {
try {
System.out.printf("Thread name is: [%s], thread id is: [%d].\n", Thread.currentThread().getName(),Thread.currentThread().getId());
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
re[0] = new RuntimeException("interrupted " + Thread.currentThread().getId() + " thread success.");
}
}
};
Thread interruptMe = new Thread(runnable,threadName);
Thread interruptMe1 = new Thread(runnable,threadName);
interruptMe.start();
interruptMe1.start();
VmTool tool = initVmTool();
tool.interruptSpecialThread((int) interruptMe.getId());
TimeUnit.SECONDS.sleep(5);
Assert.assertEquals(("interrupted " + interruptMe.getId() + " thread success."), re[0].getMessage());
}
}

View File

@ -55,6 +55,7 @@ import arthas.VmTool;
+ " vmtool --action getInstances --className java.lang.String --limit 10\n"
+ " vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext\n"
+ " vmtool --action forceGc\n"
+ " vmtool --action interruptThread -t 1\n"
+ Constants.WIKI + Constants.WIKI_HOME + "vmtool")
//@formatter:on
public class VmToolCommand extends AnnotatedCommand {
@ -63,7 +64,7 @@ public class VmToolCommand extends AnnotatedCommand {
private VmToolAction action;
private String className;
private String express;
private int threadId;
private String hashCode = null;
private String classLoaderClass;
/**
@ -149,8 +150,14 @@ public class VmToolCommand extends AnnotatedCommand {
this.express = express;
}
@Option(shortName = "t", longName = "threadId", required = false)
@Description("The id of the thread to be interrupted")
public void setThreadId(int threadId) {
this.threadId = threadId;
}
public enum VmToolAction {
getInstances, forceGc
getInstances, forceGc, interruptThread
}
@Override
@ -225,6 +232,12 @@ public class VmToolCommand extends AnnotatedCommand {
vmToolInstance().forceGc();
process.write("\n");
process.end();
return;
} else if (VmToolAction.interruptThread.equals(action)) {
vmToolInstance().interruptSpecialThread(threadId);
process.write("\n");
process.end();
return;
}