alibaba / jvm-sandbox

Real - time non-invasive AOP framework container based on JVM
GNU Lesser General Public License v3.0
6.77k stars 1.56k forks source link

springboot下Module中使用宿主应用类报错ClassNotFoundException #444

Open fawen18 opened 12 months ago

fawen18 commented 12 months ago

背景: 对MySQL driver进行增强,监控执行sql耗时

启动脚本: java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8003 -javaagent:${HOME}/sandbox/lib/sandbox-agent.jar uniqueauth.jar 这里是关键,使用的是springboot的fatjar,由于springboot有自己的classloader,所以导致下面的问题(我的猜测)。

代码如下: `@MetaInfServices(Module.class) @Information(id = "MySQLMonitorModule", version = "0.0.1", author = "") public class MySQLMonitorModule implements Module, LoadCompleted { @Resource private ModuleEventWatcher moduleEventWatcher;

@Override
public void loadCompleted() {
    new EventWatchBuilder(moduleEventWatcher)
            .onClass("com.mysql.jdbc.MySQLConnection")
            .includeSubClasses()
            .includeBootstrap()
            .onBehavior("execSQL")
            .onWatch(new AdviceListener() {
                @Override
                protected void before(Advice advice) throws Throwable {
                    long start = System.currentTimeMillis();
                    advice.attach(start);
                }

                @Override
                protected void afterReturning(Advice advice) throws Throwable {
                    StatementImpl callingStatement = (StatementImpl) advice.getParameterArray()[0];

                }

                @Override
                protected void afterThrowing(Advice advice) throws Throwable {
                }
            });
}

}`

报错如下: image 其中com.mysql.jdbc.StatementImpl该类为宿主应用类

@oldmanpushcart @dongchenxu 求大神帮助

lemon0029 commented 11 months ago

是用的 jvm-sandbox v1.4.0 吗?我也遇到的同样的问题,排查发现 v1.3.3 是没有问题的,因为存在 BusinessClassLoaderHolder 的缘故,ModuleJarClassLoader 在加载不到类时会自动去通过 BusinessClassLoader 加载,不过这部分内容在 v1.4.0 中删除了...现在也没有什么好办法解决这个问题。

fawen18 commented 11 months ago

是jvm-sandbox v1.4.0,不能使用宿主类编程特别不方便,现在只能使用反射来处理!!!

lemon0029 commented 11 months ago

是jvm-sandbox v1.4.0,不能使用宿主类编程特别不方便,现在只能使用反射来处理!!!

模块中 AdviceListener 数量比较少还好哦,我们这几十上百个,都要这么改的话实在太麻烦了。打算实现一个 ClassLoader 然后再实现一个 EventListener 来包装现有的代码了,可行性感觉没问题,但是这样子相当于就是把 jvm-sandbox-api 再包了一层,非常怪异...折腾下来给我的感觉就是 jvm-sandbox 这个所谓的 “小版本” 升级真不靠谱,明明 1.3.3 还好好的,升级到 1.4.0 就不行了,但是不升级吧,现在已经遇到了性能瓶颈,测试 1.4.0 又能提升 50% 左右到性能,不升级也说不过去...

Aresxue commented 11 months ago

盲猜一下估计是为了实现比较严谨的类加载器隔离,像淘宝的Pandora那样,不隔离的后果到后期真的会很坑爹。但是这一点该在release note中提一下,可以扩展下AdviceListener——自己找到类加载器然后swap一下。

z529192557 commented 9 months ago

BusinessClassLoaderHolder 的设计是不够严谨的,只能解决部分类加载关系比较简单的场景

z529192557 commented 9 months ago

如果 BusinessClassLoaderHolder 对各位的帮助确实很大,可以拉个分支,把1.3.3版本之前 BusinessClassLoaderHolder 的逻辑重新合并回去,打一个适应自己业务的sandbox包

oldmanpushcart commented 5 months ago

纠结啊,要不要保留BusinessClassLoaderHolder呢,好纠结啊啊啊。但如果有,真的会出非常不可预期的Cast异常。不严谨。 @z529192557 我也想在主干上继续保留这个功能,但必须更精简、更可控。

z529192557 commented 3 months ago

纠结啊,要不要保留BusinessClassLoaderHolder呢,好纠结啊啊啊。但如果有,真的会出非常不可预期的Cast异常。不严谨。 @z529192557 我也想在主干上继续保留这个功能,但必须更精简、更可控。

@oldmanpushcart 要不然在1.4.1中折中保留吧,默认不开启,在properties中提供开关来帮助大家开启这个小小的特性,在完美方案想好之前过度一下?