xjar
xjar copied to clipboard
使用xjar启动器启动集成了seata-all-1.3.0.jar的加密后的Spring Cloud项目时发生异常
我在项目中加入了xjar的Maven插件依赖,即在pom.xml中的project->build->plugins加入如下代码
<plugin>
<groupId>com.github.core-lib</groupId>
<artifactId>xjar-maven-plugin</artifactId>
<version>4.0.2</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
<configuration>
<password>pswd</password>
</configuration>
</execution>
</executions>
</plugin>
并在project->pluginRepositories加入如下代码:
<pluginRepository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</pluginRepository>
完成编译后,启动时打印了以下异常堆栈:
2022-10-18 21:09:01.574 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
io.seata.common.loader.EnhancedServiceNotFoundException: not found service provider for : io.seata.sqlparser.util.DbTypeParser caused by java.lang.IllegalStateException: Extension instance(definition: io.seata.common.loader.ExtensionDefinition@e625a923, class: interface io.seata.sqlparser.util.DbTypeParser) could not be instantiated: Incompatible magic value 1873398948 in class file io/seata/sqlparser/druid/DruidDbTypeParserImpl
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.createNewExtension(EnhancedServiceLoader.java:406)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.getExtensionInstance(EnhancedServiceLoader.java:388)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.loadExtension(EnhancedServiceLoader.java:360)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.load(EnhancedServiceLoader.java:249)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.access$200(EnhancedServiceLoader.java:190)
at io.seata.common.loader.EnhancedServiceLoader.load(EnhancedServiceLoader.java:82)
at io.seata.rm.datasource.util.JdbcUtils.getDbTypeParser(JdbcUtils.java:46)
at io.seata.rm.datasource.util.JdbcUtils.getDbType(JdbcUtils.java:57)
at io.seata.rm.datasource.DataSourceProxy.init(DataSourceProxy.java:92)
at io.seata.rm.datasource.DataSourceProxy.<init>(DataSourceProxy.java:85)
at io.seata.rm.datasource.DataSourceProxy.<init>(DataSourceProxy.java:74)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at io.seata.spring.annotation.datasource.DataSourceProxyHolder.putDataSource(DataSourceProxyHolder.java:64)
at io.seata.spring.annotation.datasource.SeataAutoDataSourceProxyAdvice.invoke(SeataAutoDataSourceProxyAdvice.java:34)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.alibaba.druid.pool.DruidDataSource$$EnhancerBySpringCGLIB$$6febe76.toString(<generated>)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:626)
at org.springframework.jmx.export.MBeanExporter.lambda$registerBeans$2(MBeanExporter.java:552)
at java.util.HashMap.forEach(HashMap.java:1289)
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:552)
at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:435)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:864)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
at xxx.xx.x.Application.main(Application.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at io.xjar.boot.XJarLauncher.launch(XJarLauncher.java:26)
at io.xjar.boot.XJarLauncher.main(XJarLauncher.java:22)
Caused by: java.lang.ClassFormatError: Incompatible magic value 1873398948 in class file io/seata/sqlparser/druid/DruidDbTypeParserImpl
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at io.seata.sqlparser.druid.DruidIsolationClassLoader.loadInternalClass(DruidIsolationClassLoader.java:53)
at io.seata.sqlparser.druid.DruidIsolationClassLoader.loadClass(DruidIsolationClassLoader.java:42)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at io.seata.sqlparser.druid.DruidDelegatingDbTypeParser.setClassLoader(DruidDelegatingDbTypeParser.java:42)
at io.seata.sqlparser.druid.DruidDelegatingDbTypeParser.<init>(DruidDelegatingDbTypeParser.java:32)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.initInstance(EnhancedServiceLoader.java:573)
at io.seata.common.loader.EnhancedServiceLoader$InnerEnhancedServiceLoader.createNewExtension(EnhancedServiceLoader.java:402)
... 41 more
经过排查,发现抛出异常的方法代码如下:
/**
* init instance
*
* @param implClazz the impl clazz
* @param argTypes the arg types
* @param args the args
* @return s s
* @throws IllegalAccessException the illegal access exception
* @throws InstantiationException the instantiation exception
* @throws NoSuchMethodException the no such method exception
* @throws InvocationTargetException the invocation target exception
*/
private S initInstance(Class implClazz, Class[] argTypes, Object[] args)
throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
S s = null;
if (argTypes != null && args != null) {
// Constructor with arguments
Constructor<S> constructor = implClazz.getDeclaredConstructor(argTypes);
s = type.cast(constructor.newInstance(args));
} else {
// default Constructor
s = type.cast(implClazz.newInstance());
}
if (s instanceof Initialize) {
((Initialize)s).init();
}
return s;
}
其中s = type.cast(implClazz.newInstance());这里调用Class#newInstance()方法抛出了异常,异常中所述无法被实例化的接口代码如下:
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.sqlparser.util;
/**
* @author ggndnn
*/
public interface DbTypeParser {
String parseFromJdbcUrl(String jdbcUrl);
}
提示魔数不兼容的类代码如下:
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.sqlparser.druid;
import com.alibaba.druid.util.JdbcUtils;
import io.seata.sqlparser.util.DbTypeParser;
/**
* @author ggndnn
*/
class DruidDbTypeParserImpl implements DbTypeParser {
@Override
public String parseFromJdbcUrl(String jdbcUrl) {
return JdbcUtils.getDbType(jdbcUrl, null);
}
}
这两个Java文件都在seata-all-1.3.0.jar这个包中,这个包的MANIFEST.MF文件内容如下:
Manifest-Version: 1.0
Implementation-Title: Seata All-in-one 1.3.0
Implementation-Version: 1.3.0
Built-By: min.ji
Specification-Vendor: Seata
Specification-Title: Seata All-in-one 1.3.0
Implementation-Vendor-Id: io.seata
Implementation-Vendor: Seata
Implementation-Build: 2020-07-15T17:30:56Z
Created-By: Apache Maven 3.6.0
Build-Jdk: 1.8.0_181
Specification-Version: 1.3
Implementation-URL: http://seata.io
以上是排查过程以及全部的相关信息,希望能够对定位问题有所帮助,非常感谢!
seata 是基于蚂蚁SOFAboot的吧,它里面为了做模块隔离和类隔离,自定义了Classloader。xjar应该是不能直接用了,需要根据SOFAboot ark的相关原理修改xjar
seata 是基于蚂蚁SOFAboot的吧,它里面为了做模块隔离和类隔离,自定义了Classloader。xjar应该是不能直接用了,需要根据SOFAboot ark的相关原理修改xjar
非常感谢。
seata可以用,排掉就行了
<exclude>META-INF/**/*</exclude>
<exclude>io/seata/**</exclude>
<exclude>LICENSE</exclude>
<exclude>lib/sqlparser/*</exclude>