Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
scouter.agent.util.AsyncRunner Maven / Gradle / Ivy
/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package scouter.agent.util;
import scouter.agent.JavaAgent;
import scouter.agent.Logger;
import scouter.agent.netio.data.DataProxy;
import scouter.agent.summary.ErrorData;
import scouter.agent.summary.ServiceSummary;
import scouter.lang.AlertLevel;
import scouter.lang.TextTypes;
import scouter.lang.pack.AlertPack;
import scouter.lang.value.MapValue;
import scouter.util.*;
import java.lang.instrument.ClassDefinition;
import java.util.ArrayList;
import static scouter.agent.util.DumpUtil.conf;
public class AsyncRunner extends Thread {
private static AsyncRunner instance = null;
private RequestQueue queue = new RequestQueue(1024);
public final static synchronized AsyncRunner getInstance() {
if (instance == null) {
instance = new AsyncRunner();
instance.setDaemon(true);
instance.setName(ThreadUtil.getName(instance));
instance.start();
}
return instance;
}
private static class Hook {
public Hook(ClassLoader loader, String classname, byte[] body) {
super();
this.loader = loader;
this.classname = classname.replace('/', '.');
this.body = body;
}
ClassLoader loader;
String classname;
byte[] body;
}
private static class RedefineClasses {
StringSet classnames;
public RedefineClasses(StringSet classnames) {
this.classnames = classnames;
}
}
public void add(ClassLoader loader, String classname, byte[] body) {
queue.put(new Hook(loader, classname, body));
}
public void add(LeakInfo data) {
queue.put(data);
}
public void add(LeakInfo2 data) {
queue.put(data);
}
public void add(Runnable r) {
queue.put(r);
}
public void add(StringSet classnames) {
queue.put(new RedefineClasses(classnames));
}
public void run() {
while (true) {
Object m = queue.get(1000);
try {
if (m instanceof Hook) {
hooking((Hook) m);
} else if (m instanceof LeakInfo) {
alert((LeakInfo) m);
} else if (m instanceof LeakInfo2) {
alert((LeakInfo2) m);
} else if (m instanceof Runnable) {
process((Runnable) m);
} else if (m instanceof RedefineClasses) {
redefine(((RedefineClasses) m).classnames);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
private void redefine(StringSet clazzes) {
Class[] loadedClasses = JavaAgent.getInstrumentation().getAllLoadedClasses();
ArrayList definitionList = new ArrayList();
boolean allSuccess = true;
for (int i = 0; i < loadedClasses.length; i++) {
if (clazzes.hasKey(loadedClasses[i].getName())) {
try {
byte[] buff = ClassUtil.getByteCode(loadedClasses[i]);
if (buff == null) {
continue;
}
definitionList.add(new ClassDefinition(loadedClasses[i], buff));
} catch (Exception e) {
allSuccess = false;
break;
}
}
}
if (definitionList.size() > 0 && allSuccess) {
try {
JavaAgent.getInstrumentation().redefineClasses(definitionList.toArray(new ClassDefinition[definitionList.size()]));
} catch (Throwable th) {
Logger.println("A183", "redefine error : " + loadedClasses);
}
}
}
private void process(Runnable r) {
r.run();
}
private void alert(LeakInfo leakInfo) {
ServiceSummary summary = ServiceSummary.getInstance();
MapValue mv = new MapValue();
mv.put(AlertPack.HASH_FLAG + TextTypes.SERVICE + "_service-name", leakInfo.serviceHash);
if (leakInfo.fullstack) {
ErrorData d = summary.process(leakInfo.error, 0, leakInfo.serviceHash, leakInfo.txid, 0, 0);
Logger.println("A156", leakInfo.error + " " + leakInfo.inner);
if (d != null && d.fullstack == 0) {
String fullstack = ThreadUtil.getStackTrace(leakInfo.error.getStackTrace(), leakInfo.fullstackSkip);
d.fullstack = DataProxy.sendError(fullstack);
Logger.println("A157", fullstack);
}
mv.put(AlertPack.HASH_FLAG + TextTypes.ERROR + "_full-stack", d.fullstack);
} else {
summary.process(leakInfo.error, 0, leakInfo.serviceHash, leakInfo.txid, 0, 0);
Logger.println("A179", leakInfo.error + " " + leakInfo.inner);
}
DataProxy.sendAlert(AlertLevel.WARN, "CONNECTION_NOT_CLOSE", "Connection may not closed", mv);
}
private void alert(LeakInfo2 leakInfo2) {
ServiceSummary summary = ServiceSummary.getInstance();
MapValue mv = new MapValue();
mv.put(AlertPack.HASH_FLAG + TextTypes.SERVICE + "_service-name", leakInfo2.serviceHash);
if (leakInfo2.fullstack) {
ErrorData d = summary.process(leakInfo2.error, 0, leakInfo2.serviceHash, leakInfo2.txid, 0, 0);
Logger.println("A156", leakInfo2.error + " " + leakInfo2.innerObject);
if (d != null && d.fullstack == 0) {
String fullstack = ThreadUtil.getStackTrace(leakInfo2.error.getStackTrace(), leakInfo2.fullstackSkip);
d.fullstack = DataProxy.sendError(fullstack);
Logger.println("A157", fullstack);
}
mv.put(AlertPack.HASH_FLAG + TextTypes.ERROR + "_full-stack", d.fullstack);
} else {
summary.process(leakInfo2.error, 0, leakInfo2.serviceHash, leakInfo2.txid, 0, 0);
Logger.println("A179", leakInfo2.error + " " + leakInfo2.innerObject);
}
DataProxy.sendAlert(AlertLevel.WARN, "CONNECTION_NOT_CLOSE", "Connection may not closed", mv);
if(conf._trace) Logger.trace("[Force-Close-InnerObject]" + System.identityHashCode(leakInfo2.innerObject));
boolean closeResult = leakInfo2.closeManager.close(leakInfo2.innerObject);
//Logger.println("G003", "connection auto closed:" + closeResult);
}
private void hooking(Hook m) {
// Never use dynamic hooking on AIX with JDK1.5
if (SystemUtil.IS_AIX && SystemUtil.IS_JAVA_1_5) {
return;
}
try {
Class cls = Class.forName(m.classname, false, m.loader);
ClassDefinition[] cd = new ClassDefinition[1];
cd[0] = new ClassDefinition(cls, m.body);
JavaAgent.getInstrumentation().redefineClasses(cd);
} catch (Throwable t) {
Logger.println("A149", "async hook fail:" + m.classname + " " + t);
}
}
}