1. ホーム
  2. ジャワ

xStream xml から java bean へ、CannotResolveClassException をスローする原因。

2022-02-26 01:35:30

この2日間、xStreamを使ってxmlとjava beanを相互に転送する開発をしていて、奇妙な問題に遭遇しました。Java BeanのすべてにeclipseのXMLで実行すると、製品にインポートされたCannotResolveClassException例外がスローされますので、原因を見つけるために開始され、うまくいっています。

具体的な例外メッセージは以下の通りです。

原因:com.thoughtworks.xstream.mapper.CannotResolveClassException: com.test.bean.FunctionAccess



DefaultMapper.realClass(DefaultMapper.java:56) ~[xstream-1.4.2.jar:na] at com.thoughtworks.xstream.mapper.



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) ~[xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readItem(AbstractCollectionConverter.java:70) ~[ xstream-1.4.2.jar:na ]。



at com.thoughtworks.xstream.converters.collections.CollectionConverter.addCurrentElementToCollection(CollectionConverter.java:79) ~[ xstream-1.4.2.jar:na].



at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:72) ~[xstream-1.4 .2.jar:na].



at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:66) ~[xstream-1.4 .2.jar:na] となります。



at com.thoughtworks.xstream.converters.collections.CollectionConverter.unmarshal(CollectionConverter.java:61) ~[xstream-1.4.2.jar:na ]である。



at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) ~[xstream-1.4.2.jar:na].

まずコードに問題がないか、様々なアノテーションと生成されたxmlの比較を確認しました。

その後、エクスポートした jar パッケージに問題がないか、またエクスポートした jar パッケージが完全であることを確認するために、エクスポートした jar パッケージを逆コンパイルしました。

いろいろと試してみたのですが、原因がわからず、とうとうソースコードを見ることになりました。

やっと見つけたのが、xstreamのDefaultMapperクラスのrealClassメソッドです。

  public Class realClass(String elementName)



    { <未定義



        試みる



        { <未定義



            if(elementName.startsWith(XSTREAM_PACKAGE_ROOT))



                return com/thoughtworks/xstream/mapper/DefaultMapper.getClassLoader().loadClass(elementName);



        }



        catch(ClassNotFoundException e)



        { <未定義



            new CannotResolveClassException(elementName)をスローします。



        }



        if(elementName.charAt(0) ! = '[')



            return classLoader.loadClass(elementName);



        if(elementName.endsWith(";"))



            return Class.forName(elementName.toString(), false, classLoader);



        return Class.forName(elementName.toString());



    }

ソースコードを見直してみると、CannotResolveClassException例外は実はClassNotFoundException例外であることがわかったので、なぜクラスが見つからないのかを調べ始め、逆コンパイルしてクラスが存在することを確認しました。そこで、xstream の jar パッケージを探したところ、結局、製品グループによる別の jar パッケージの lib ディレクトリ内に配置されていることが分かりました。

これは、Class.getClassLoader().loadClass(elementName);を呼び出したときに、jarパッケージのlibディレクトリにあるjar内のクラスが外部のjarが書き込んだjavaオブジェクトを見つけられないためと思われる。

結局、製品のjarパッケージからxstreamに必要ないくつかのjarパッケージを取り出したらうまくいきました。なんという奇妙な問題で2日間も時間を無駄にしてしまったのでしょう。

しかし、プロジェクトが直接jar内の製品を変更しに行くことができないため、最終的にはJAXBに切り替えてxmlとjava beanの相互交換を実現し、上記の問題はありません。