in core/src/main/java/com/taobao/arthas/core/command/monitor200/EnhancerCommand.java [145:230]
protected void enhance(CommandProcess process) {
Session session = process.session();
if (!session.tryLock()) {
String msg = "someone else is enhancing classes, pls. wait.";
process.appendResult(new EnhancerModel(null, false, msg));
process.end(-1, msg);
return;
}
EnhancerAffect effect = null;
int lock = session.getLock();
try {
Instrumentation inst = session.getInstrumentation();
AdviceListener listener = getAdviceListenerWithId(process);
if (listener == null) {
logger.error("advice listener is null");
String msg = "advice listener is null, check arthas log";
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(-1, msg);
return;
}
boolean skipJDKTrace = false;
if(listener instanceof AbstractTraceAdviceListener) {
skipJDKTrace = ((AbstractTraceAdviceListener) listener).getCommand().isSkipJDKTrace();
}
Enhancer enhancer = new Enhancer(listener, listener instanceof InvokeTraceable, skipJDKTrace, getClassNameMatcher(), getClassNameExcludeMatcher(), getMethodNameMatcher());
// 注册通知监听器
process.register(listener, enhancer);
effect = enhancer.enhance(inst, this.maxNumOfMatchedClass);
if (effect.getThrowable() != null) {
String msg = "error happens when enhancing class: "+effect.getThrowable().getMessage();
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(1, msg + ", check arthas log: " + LogUtil.loggingFile());
return;
}
if (effect.cCnt() == 0 || effect.mCnt() == 0) {
// no class effected
if (!StringUtils.isEmpty(effect.getOverLimitMsg())) {
process.appendResult(new EnhancerModel(effect, false));
process.end(-1);
return;
}
// might be method code too large
process.appendResult(new EnhancerModel(effect, false, "No class or method is affected"));
String smCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("sm CLASS_NAME METHOD_NAME").reset().toString();
String optionsCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("options unsafe true").reset().toString();
String javaPackage = Ansi.ansi().fg(Ansi.Color.GREEN).a("java.*").reset().toString();
String resetCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("reset CLASS_NAME").reset().toString();
String logStr = Ansi.ansi().fg(Ansi.Color.GREEN).a(LogUtil.loggingFile()).reset().toString();
String issueStr = Ansi.ansi().fg(Ansi.Color.GREEN).a("https://github.com/alibaba/arthas/issues/47").reset().toString();
String msg = "No class or method is affected, try:\n"
+ "1. Execute `" + smCommand + "` to make sure the method you are tracing actually exists (it might be in your parent class).\n"
+ "2. Execute `" + optionsCommand + "`, if you want to enhance the classes under the `" + javaPackage + "` package.\n"
+ "3. Execute `" + resetCommand + "` and try again, your method body might be too large.\n"
+ "4. Match the constructor, use `<init>`, for example: `watch demo.MathGame <init>`\n"
+ "5. Check arthas log: " + logStr + "\n"
+ "6. Visit " + issueStr + " for more details.";
process.end(-1, msg);
return;
}
// 这里做个补偿,如果在enhance期间,unLock被调用了,则补偿性放弃
if (session.getLock() == lock) {
if (process.isForeground()) {
process.echoTips(Constants.Q_OR_CTRL_C_ABORT_MSG + "\n");
}
}
process.appendResult(new EnhancerModel(effect, true));
//异步执行,在AdviceListener中结束
} catch (Throwable e) {
String msg = "error happens when enhancing class: "+e.getMessage();
logger.error(msg, e);
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(-1, msg);
} finally {
if (session.getLock() == lock) {
// enhance结束后解锁
process.session().unLock();
}
}
}