Skip to content
This repository has been archived by the owner on Oct 23, 2024. It is now read-only.

java.lang.ClassNotFoundException: com.alibaba.fastjson.serializer.SerializeFilterable #616

Closed
zhihuij opened this issue May 6, 2016 · 13 comments
Milestone

Comments

@zhihuij
Copy link

zhihuij commented May 6, 2016

java.lang.ClassNotFoundException: com.alibaba.fastjson.serializer.SerializeFilterable
java.lang.ClassLoader.findClass(ClassLoader.java:531)
java.lang.ClassLoader.loadClass(ClassLoader.java:425)
java.lang.ClassLoader.loadClass(ClassLoader.java:358)
java.lang.Class.getDeclaredConstructors0(Native Method)
java.lang.Class.privateGetDeclaredConstructors(Class.java:2532)
java.lang.Class.getConstructor0(Class.java:2842)
java.lang.Class.newInstance(Class.java:345)
com.alibaba.fastjson.serializer.ASMSerializerFactory.createJavaBeanSerializer(ASMSerializerFactory.java:438)
com.alibaba.fastjson.serializer.SerializeConfig.createASMSerializer(SerializeConfig.java:99)
com.alibaba.fastjson.serializer.SerializeConfig.createJavaBeanSerializer(SerializeConfig.java:137)
com.alibaba.fastjson.serializer.SerializeConfig.getObjectWriter(SerializeConfig.java:425)
com.alibaba.fastjson.serializer.JSONSerializer.getObjectWriter(JSONSerializer.java:320)
com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:263)
com.alibaba.fastjson.JSON.toJSONString(JSON.java:562)
com.alibaba.fastjson.JSON.toJSONString(JSON.java:504)
com.alibaba.fastjson.JSON.toJSONString(JSON.java:469)

场景:fastjson由一个URLClassLoader加载,这个ClassLoader的parent是SystemClassLoader。
在由SystemClassLoader加的类A中通过反射生成URLClassLoader加载的一个类B并生成一个对象b,然后调用该对象b的一个接口,这个接口内部调用 JSON.toJSONString。
版本:1.2.11

@wenshao
Copy link
Member

wenshao commented May 6, 2016

有点绕哦,能否帮我做一个重现问题的testcase?另外怀疑同时存在两个版本的fastjson

fastjson有专门处理这样问题代码的,不知道为啥不起作用,你能否帮忙在你的环境调试一下

// com.alibaba.fastjson.util.ASMClassLoader.isExternalClass
public boolean isExternalClass(Class<?> clazz) {
    ClassLoader classLoader = clazz.getClassLoader();

    if (classLoader == null) {
        return false;
    }

    ClassLoader current = this;
    while (current != null) {
        if (current == classLoader) {
            return false;
        }

        current = current.getParent();
    }

    return true;
}

@zhihuij
Copy link
Author

zhihuij commented May 7, 2016

是有两个版本fastjson,使用独立的ClassLoader就是为了避免版本冲突,刚才试了下,去掉另外一个fastjson的依赖,没有这个异常,所以应该还是classloader的逻辑有问题

@zhihuij
Copy link
Author

zhihuij commented May 7, 2016

跟踪了下,这个isExternalClass跟报的异常MS没什么关系,这个isExternalClass被调用时的现场:
com.alibaba.fastjson.util.ASMClassLoader@39ce89aa => java.net.URLClassLoader@3fa1732d!!!sun.misc.Launcher$AppClassLoader@4aa0560e
com.C ===> sun.misc.Launcher$AppClassLoader@4aa0560e !!!!sun.misc.Launcher$ExtClassLoader@6471d768

第一行是触发ASMClassLoader.isExternalClass调用时,ASMClassLoader的classloader以及它的parent;
第二行是isExternalClass函数参数,class对象对应的类名,classloader及parent。

@zhihuij
Copy link
Author

zhihuij commented May 7, 2016

om.alibaba.fastjson.util.ASMClassLoader@1cea9777 => java.net.URLClassLoader@3fa1732d!!!sun.misc.Launcher$AppClassLoader@4aa0560e
com.alibaba.fastjson.serializer.ASMSerializer_1_Transaction ===> com.alibaba.fastjson.util.ASMClassLoader@1cea9777 !!!!WebappClassLoader

挺诡异的结果,第一行是调用 isExternalClass 时,ASMClassLoader的父子关系ASMClassLoader本身这个Class的classloader的父子关系
第二行是调用 defineClassPublic 时 ASMClassLoader的父子关系:(com.alibaba.fastjson.serializer.ASMSerializer_1_Transaction 是 传入 defineClassPublic 的第一个参数),后面是返回的Class对象的classloader及parent

在两次调用之间有修改过 ASMClassLoader@1cea9777 的parent?

@wenshao
Copy link
Member

wenshao commented May 7, 2016

这个改不了的吧,很诡异哦,另问1.2.8有问题么?

@zhihuij
Copy link
Author

zhihuij commented May 7, 2016

刚才的评论有问题,我已经在原来的评论上编辑了下,这个问题主要是跟 ASMClassLoader 的 getParentClassLoader的逻辑有关,当 Thread.currentThread().getContextClassLoader() 能加载到JSON这个类,但跟ASMClassLoader 本身不在一个版本的包里时,就会出问题。

具体到我这个场景:
ASMClassLoader 类(fastjson 1.2.11)由 java.net.URLClassLoader 加载,
但Thread.currentThread().getContextClassLoader() = WebappClassLoader (这个ClassLoader的classpath下包含 1.1.26的fastjson,所以能加载到JSON这个类),所以创建出来的 ASMClassLoader 的parent是WebappClassLoader,导致后面的类加载失败。

所以我觉得getParentClassLoader逻辑需要调整一下,简单的设置为ASMClassLoader类的classloader就行了吧

Update:看了下ASMClassLoader的更改历史,MS之前为了修复什么bug由直接用ASMClassLoader的classloader改成了目前这种形式

@wenshao
Copy link
Member

wenshao commented May 8, 2016

先用这样办法解决吧

ParserConfig.global = new ParserConfig(ClassLoader);

也希望你能帮忙想办法

@zhihuij
Copy link
Author

zhihuij commented May 8, 2016

这个没啥用,这个可能改变ASMDeserializerFactory的ASMClassLoader,对ASMSerializerFactory不起作用,

protected final ASMClassLoader classLoader = new ASMClassLoader();

里直接new了ASMClassLoader

@zhihuij
Copy link
Author

zhihuij commented May 8, 2016

顺便问一下,1d423d2 这个提交在修正什么问题?

@wenshao
Copy link
Member

wenshao commented May 8, 2016

我重现了问题,修改了ASMSerializerFactory的classloader,你帮忙验证一下?

@zhihuij
Copy link
Author

zhihuij commented May 9, 2016

在我的场景下试了下最新的提交,工作正常

@wenshao wenshao added this to the 1.2.12 milestone May 9, 2016
@wenshao
Copy link
Member

wenshao commented May 9, 2016

那我关闭了issue了啊,等发布吧,预计这个月底或者6月初发布

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants