首页 / JAVA / 如何使用Java检测替换新类?
如何使用Java检测替换新类?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了如何使用Java检测替换新类?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8051字,纯文字阅读大概需要12分钟。
内容图文
![如何使用Java检测替换新类?](/upload/InfoBanner/zyjiaocheng/727/aff2d559b2ad414c882b8640d9d00208.jpg)
我需要创建一个java代理,当启用它时,它获取jar文件的路径作为参数,然后它将任何已加载的类替换为jar文件中的一个,如果它们的名称匹配.
例如,我们有一个名为com.something.ClassTest的类的应用程序.现在,如果提到的jar(不在类路径中)有一个与com.something.ClassTest完全相同的类,我想用jar中的那个替换它.
我有这类变压器,但不确定这是否正确.我得到IOException,找不到消息Class.
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if(classNames.contains(className.replace("/", "."))) {
System.out.format("\n==> Found %s \n", className);
try {
Class c = urlClassLoader.loadClass(className.replace("/", "."));
InputStream is = urlClassLoader.getResourceAsStream(className.replace("/", "."));
System.out.println("Loaded class " + c);
ClassReader reader = new ClassReader(is);
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
byte[] content = writer.toByteArray();
System.out.println("Redifned " + new String(content));
System.out.println("Orig " + new String(classfileBuffer));
ClassDefinition cd = new ClassDefinition(c, content);
instrumentation.redefineClasses(cd);
return content;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnmodifiableClassException e) {
e.printStackTrace();
}
}
return classfileBuffer;
}
我得到的错误是在实例化ClassReader的行.我想这个错误是因为urlClassloader在某种程度上在当前类加载器的层次结构下…但我不知道我怎么能做到这一点.
这是初始化URL类加载的代码
public SimpleClassTransformer(Instrumentation instrumentation, String jarFileName) {
this.jarFileName = jarFileName;
if(jarFileName != null) {
JarFile jarFile = null;
try {
jarFile = new JarFile(this.jarFileName);
Enumeration e = jarFile.entries();
System.out.println("Jar file: " + this.jarFileName);
URL[] urls = { new URL("jar:file:" + this.jarFileName+"!/") };
urlClassLoader = URLClassLoader.newInstance(urls);
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
if(je.isDirectory() || !je.getName().endsWith(".class")){
continue;
}
// -6 because of .class
String jarClassName = je.getName().substring(0,je.getName().length()-6);
jarClassName = jarClassName.replace('/', '.');
System.out.println("Adding class " + jarClassName);
this.classNames.add(jarClassName);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在premain()方法中实例化变换器时设置了Instrumentation.我试图避免使用Javassist.你能帮我解决这个问题吗?
这是我得到的例外:
java.io.IOException: Class not found
at jdk.internal.org.objectweb.asm.ClassReader.readClass(ClassReader.java:484)
at jdk.internal.org.objectweb.asm.ClassReader.<init>(ClassReader.java:453)
at com.agent.SimpleClassTransformer.transform(SimpleClassTransformer.java:79)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:394)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1397)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1344)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:628)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:597)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1445)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:445)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:415)
at org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DefaultDispatcherServletCondition.checkServlets(DispatcherServletAutoConfiguration.java:141)
at org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DefaultDispatcherServletCondition.getMatchOutcome(DispatcherServletAutoConfiguration.java:131)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:203)
at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:336)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:248)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:231)
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:509)
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:454)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:321)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:98)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:677)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:519)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:295)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101)
====编辑====
在解决了url类加载器的问题后,我现在得到Spring在尝试刷新其上下文时发生的错误:
TestClass has been compiled by a more recent version of the Java Runtime (class file version 0.0), this version of the Java Runtime only recognizes class file versions up to 52.0
解决方法:
另一种解决问题的方法是使用背书.
保留要在库中加载的类,并提供-Djava.endorsed.dirs =< directory_path>作为程序的JVM参数.
在加载类时,JVM首先检查此目录中的类可用性,如果未找到,则它将检查应用程序类.
这完全正常,没有任何问题,没有任何编码.
内容总结
以上是互联网集市为您收集整理的如何使用Java检测替换新类?全部内容,希望文章能够帮你解决如何使用Java检测替换新类?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。