TreeSet引发的OSGI服务代理创建异常
来源:互联网 发布:易语言调用js脚本 编辑:程序博客网 时间:2024/06/06 09:26
看故障日志:
Method entry: getService, args org.apache.karaf.deployer.features.FeatureDeploymentListener@4c500c2d2017-12-01 14:12:24,220 | INFO | REF-CHECK-THREAD | ServiceRecipe | 15 - org.apache.aries.blueprint.core - 1.4.2 | Unable to create a proxy object for the service .component-1 defined in bundle org.apache.karaf.deployer.features at version 3.0.3 with id 21. Returning the original object instead.
2017-11-28 09:09:53,117 | INFO | REF-CHECK-THREAD | ServiceRecipe | 15 - org.apache.aries.blueprint.core - 1.4.2 | Unable to create a proxy object for the service .component-2 defined in bundle org.apache.karaf.features.core at version 3.0.3 with id 20. Returning the original object instead.org.apache.aries.proxy.UnableToProxyException: java.lang.ClassFormatError: Duplicate interface name in class file Proxy7a227df2_4c60_4139_af16_c6a2cf4564f4at org.apache.aries.proxy.impl.interfaces.ProxyClassLoader.createProxyClass(ProxyClassLoader.java:165)[11:org.apache.aries.proxy.impl:1.0.5]at org.apache.aries.proxy.impl.interfaces.InterfaceProxyGenerator.getProxyInstance(InterfaceProxyGenerator.java:97)[11:org.apache.aries.proxy.impl:1.0.5]at org.apache.aries.proxy.impl.AsmProxyManager.createNewProxy(AsmProxyManager.java:80)[11:org.apache.aries.proxy.impl:1.0.5]at org.apache.aries.proxy.impl.AbstractProxyManager.createDelegatingInterceptingProxy(AbstractProxyManager.java:75)[11:org.apache.aries.proxy.impl:1.0.5]at org.apache.aries.proxy.impl.AbstractProxyManager.createInterceptingProxy(AbstractProxyManager.java:53)[11:org.apache.aries.proxy.impl:1.0.5]at org.apache.aries.blueprint.container.ServiceRecipe$TriggerServiceFactory.getService(ServiceRecipe.java:545)at org.eclipse.osgi.internal.serviceregistry.ServiceUse$1.run(ServiceUse.java:141)at java.security.AccessController.doPrivileged(Native Method)[:1.8.0_121]at org.eclipse.osgi.internal.serviceregistry.ServiceUse.getService(ServiceUse.java:139)at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:468)at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:467)at org.eclipse.osgi.framework.internal.core.BundleContextImpl.getService(BundleContextImpl.java:594)at com.zte.sdn.oscp.commons.utils.BundleUtils.getService(BundleUtils.java:123)at com.zte.sdn.oscp.framework.service.metainfo.impl.ServiceMetaTrackerManagerImpl.addTarget(ServiceMetaTrackerManagerImpl.java:32)at com.zte.sdn.oscp.framework.service.metainfo.impl.OSGiMetaTrackerServiceImpl.checkServiceReferences(OSGiMetaTrackerServiceImpl.java:121)[136:com.zte.sdn.oscp.oscp-os.oscp-framework-service:2.2.9.10R2B10]at java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator.forEachRemaining(ConcurrentLinkedQueue.java:857)[:1.8.0_121]at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)[:1.8.0_121]at com.zte.sdn.oscp.framework.service.metainfo.impl.OSGiMetaTrackerServiceImpl.checkStartedServiceReferences(OSGiMetaTrackerServiceImpl.java:116)[136:com.zte.sdn.oscp.oscp-os.oscp-framework-service:2.2.9.10R2B10]at com.zte.sdn.oscp.framework.service.metainfo.impl.OSGiMetaTrackerServiceImpl.checkServiceReferences(OSGiMetaTrackerServiceImpl.java:93)[136:com.zte.sdn.oscp.oscp-os.oscp-framework-service:2.2.9.10R2B10]at java.lang.Thread.run(Thread.java:745)[:1.8.0_121]Caused by: java.lang.ClassFormatError: Duplicate interface name in class file Proxy7a227df2_4c60_4139_af16_c6a2cf4564f4at java.lang.ClassLoader.defineClass1(Native Method)[:1.8.0_121]at java.lang.ClassLoader.defineClass(ClassLoader.java:763)[:1.8.0_121]at org.apache.aries.proxy.impl.interfaces.ProxyClassLoader.createProxyClass(ProxyClassLoader.java:157)... 19 more
从上面的日志,其异常信息是指是在创建服务代理类时,类格式错误。虽然在代码创建不成功后,会返回原始对象,对于功能目前暂无影响,但基于blueprint的延迟加载,或自定义的服务跟踪存在不可控的风险。
对于代理类的创建,并没有使用JDK和CGLIB的动态代码方式:
try { byte[] bytes = icca.generateBytes(); Class<?> c = defineClass(className, bytes, 0, bytes.length, PROXY_PROTECTION_DOMAIN); String old = classes.putIfAbsent(createSet, className); if(old != null) { c = Class.forName(className, false, this); } return c; } catch (ClassFormatError cfe) { throw new UnableToProxyException(createSet.iterator().next(), cfe); } catch (ClassNotFoundException e) { throw new UnableToProxyException(createSet.iterator().next(), e); }
byte[] bytes = icca.generateBytes();对于需要被代码的类,通过字节数组化,再反编译成类,最终生成代理,至于为何要这么做,从代码中发现其主要是增加了权限的判断与控制。
如下的另一种应用,即为字节码进行加密控制:
@Test public void test() throws IOException, IllegalAccessException, InstantiationException { File f = new File("D:/out.file"); if (f.exists() && f.isFile()) { FileInputStream in = new FileInputStream(f); byte[] original = new byte[in.available()]; in.read(original);//got encode byte in.close(); byte[] decode = Base64.getDecoder().decode(original);// byte[] decode = original; SQClassLoader loader = new SQClassLoader(); Class hello = loader.defineClass(decode, null); Hello o = (Hello) hello.newInstance(); o.sayHello("sunquan"); } }
进一步分析报错的原因,就是在将字节转化成类时,这个类实现的接口中,有重复接口从而导致反编译错误,那为什么一个类实现的接口会有重复呢?
考虑A实现
A implement B,C
B implement C,D
A 最终实现 B,C,D而不包含两个C,在进行动态代码创建时,亦不能传入2个C接口
InterfaceProxyGenerator.java 包含了接口的组装
getProxyInstance
SortedSet<Class<?>> interfaces = createSet(ifaces)
构建接口列表,使用了TreeSet,有序不重复,至此可以发现其报错的原因,就在TreeSet中的比较器。
SortedSet<Class<?>> classes = new TreeSet<Class<?>>(new Comparator<Class<?>>() { public int compare(Class<?> object1, Class<?> object2) { if (object1.getName().equals(object2.getName())) { return 0; } else if (object1.isAssignableFrom(object2)) { // first class is parent of second, it occurs earlier in type hierarchy return -1; } else if (object2.isAssignableFrom(object1)) { // second class is subclass of first one, it occurs later in hierarchy return 1; } // types have separate inheritance trees, so it doesn't mater which one is first or second, // however we can't mark them as equal cause one of them will be removed return 1; } });
上面声明的比较器,表示父类比子类大。由于TreeSet使用的红黑树,上面的定义比较器,实际执行中是会造成数据重复插入
可以看本应该是有序无重复集合,却添加进了相同的两个A
建议修改方式:
使用Map,对类及其实现接口,预先过滤一遍,再采用上面比较器的TreeSet进行排序,则能保证无重复接口。
private void addInterface(Map<String, Class> map, Class[] cls) { for (Class c : cls) map.putIfAbsent(c.getName(), c); for (Class c : cls) { if (c.getInterfaces() != null && c.getInterfaces().length > 0) { addInterface(map, c.getInterfaces()); } } }
阅读全文
0 0
- TreeSet引发的OSGI服务代理创建异常
- OSGI--动态创建服务
- 使用OSGI的服务
- osgi加载模式引发的错误
- SpringMvc+Mybatis 创建mapper接口引发的异常
- WEB服务代理类的创建
- OSGI动态注册和创建服务
- OSGi服务:SOA的架构
- 创建动态代理服务
- 创建动态代理服务
- dubbo 创建服务代理
- SqlDataReader引发的异常
- Windows服务启动异常 System.ServiceModel.Diagnostics.TraceUtility 的类型初始值设定项引发异常
- OSGi服务
- OSGI : 使用OSGi构建面向服务的联络管理应用程序
- Equinox OSGi系列之 创建自己的OSGi应用项目
- OSGI组件启动异常的错误解决方法
- 初始化引发的"StackOverflowError" 异常
- Freemarker判断序列中是否包含某个元素
- 企业级Tomcat部署实践及安全调优(再续)
- 比特币学习之密钥
- C#高级编程(中文第七版) chap 3.2.2
- 模型
- TreeSet引发的OSGI服务代理创建异常
- Jquery鼠标点击后变色,点击另一个按钮颜色还原
- 选择排序法
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/tools/ant/launch/Launc
- org.junit.platform.commons.util.ReflectionUtils.getDefaultClassLoader()
- darwin之socket消息获取与处理
- OpenGL 入门教程实例
- Kerberos
- 欢迎使用CSDN-markdown编辑器