jacoco 源码分析 class字节码植入的冲突问题
首先看jacoco premain 入口:
/******************************************************************************** Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors* All rights reserved. This program and the accompanying materials* are made available under the terms of the Eclipse Public License v1.0* which accompanies this distribution, and is available at* http://www.eclipse.org/legal/epl-v10.html** Contributors:* Marc R. Hoffmann - initial API and implementation* *******************************************************************************/ package org.jacoco.agent.rt.internal;import java.lang.instrument.Instrumentation;import org.jacoco.core.runtime.AgentOptions; import org.jacoco.core.runtime.IRuntime; import org.jacoco.core.runtime.ModifiedSystemClassRuntime;/*** The agent which is referred as the <code>Premain-Class</code>. The agent* configuration is provided with the agent parameters in the command line.*/ public final class PreMain {private PreMain() {// no instances}/*** This method is called by the JVM to initialize Java agents.* * @param options* agent options* @param inst* instrumentation callback provided by the JVM* @throws Exception* in case initialization fails*/public static void premain(final String options, final Instrumentation inst)throws Exception {final AgentOptions agentOptions = new AgentOptions(options);final Agent agent = Agent.getInstance(agentOptions);final IRuntime runtime = createRuntime(inst);runtime.startup(agent.getData());inst.addTransformer(new CoverageTransformer(runtime, agentOptions,IExceptionLogger.SYSTEM_ERR));}private static IRuntime createRuntime(final Instrumentation inst)throws Exception {return ModifiedSystemClassRuntime.createFor(inst, "java/lang/UnknownError");}}入口函數premain:? 參數 Instrumentation類是java.lang 下面的類
public static void premain(final String options, final Instrumentation inst)throws Exception {final AgentOptions agentOptions = new AgentOptions(options);final Agent agent = Agent.getInstance(agentOptions);final IRuntime runtime = createRuntime(inst);runtime.startup(agent.getData());inst.addTransformer(new CoverageTransformer(runtime, agentOptions,IExceptionLogger.SYSTEM_ERR));}然后調用了CoverageTransformer 類,這個類和 premain同一個包下面:
看下?CoverageTransformer 類:
/******************************************************************************** Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors* All rights reserved. This program and the accompanying materials* are made available under the terms of the Eclipse Public License v1.0* which accompanies this distribution, and is available at* http://www.eclipse.org/legal/epl-v10.html** Contributors:* Marc R. Hoffmann - initial API and implementation* *******************************************************************************/ package org.jacoco.agent.rt.internal;import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.CodeSource; import java.security.ProtectionDomain;import org.jacoco.core.instr.Instrumenter; import org.jacoco.core.runtime.AgentOptions; import org.jacoco.core.runtime.IRuntime; import org.jacoco.core.runtime.WildcardMatcher;/*** Class file transformer to instrument classes for code coverage analysis.*/ public class CoverageTransformer implements ClassFileTransformer {private static final String AGENT_PREFIX;static {final String name = CoverageTransformer.class.getName();AGENT_PREFIX = toVMName(name.substring(0, name.lastIndexOf('.')));}private final Instrumenter instrumenter;private final IExceptionLogger logger;private final WildcardMatcher includes;private final WildcardMatcher excludes;private final WildcardMatcher exclClassloader;private final ClassFileDumper classFileDumper;private final boolean inclBootstrapClasses;private final boolean inclNoLocationClasses;/*** New transformer with the given delegates.* * @param runtime* coverage runtime* @param options* configuration options for the generator* @param logger* logger for exceptions during instrumentation*/public CoverageTransformer(final IRuntime runtime,final AgentOptions options, final IExceptionLogger logger) {this.instrumenter = new Instrumenter(runtime);this.logger = logger;// Class names will be reported in VM notation:includes = new WildcardMatcher(toVMName(options.getIncludes()));excludes = new WildcardMatcher(toVMName(options.getExcludes()));exclClassloader = new WildcardMatcher(options.getExclClassloader());classFileDumper = new ClassFileDumper(options.getClassDumpDir());inclBootstrapClasses = options.getInclBootstrapClasses();inclNoLocationClasses = options.getInclNoLocationClasses();}public byte[] transform(final ClassLoader loader, final String classname,final Class<?> classBeingRedefined,final ProtectionDomain protectionDomain,final byte[] classfileBuffer) throws IllegalClassFormatException {// We do not support class retransformation:if (classBeingRedefined != null) {return null;}if (!filter(loader, classname, protectionDomain)) {return null;}try {classFileDumper.dump(classname, classfileBuffer);return instrumenter.instrument(classfileBuffer, classname);} catch (final Exception ex) {final IllegalClassFormatException wrapper = new IllegalClassFormatException(ex.getMessage());wrapper.initCause(ex);// Report this, as the exception is ignored by the JVM:logger.logExeption(wrapper);throw wrapper;}}/*** Checks whether this class should be instrumented.* * @param loader* loader for the class* @param classname* VM name of the class to check* @param protectionDomain* protection domain for the class* @return <code>true</code> if the class should be instrumented*/boolean filter(final ClassLoader loader, final String classname,final ProtectionDomain protectionDomain) {if (loader == null) {if (!inclBootstrapClasses) {return false;}} else {if (!inclNoLocationClasses && !hasSourceLocation(protectionDomain)) {return false;}if (exclClassloader.matches(loader.getClass().getName())) {return false;}}return !classname.startsWith(AGENT_PREFIX) &&includes.matches(classname) &&!excludes.matches(classname);}/*** Checks whether this protection domain is associated with a source* location.* * @param protectionDomain* protection domain to check (or <code>null</code>)* @return <code>true</code> if a source location is defined*/private boolean hasSourceLocation(final ProtectionDomain protectionDomain) {if (protectionDomain == null) {return false;}final CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource == null) {return false;}return codeSource.getLocation() != null;}private static String toVMName(final String srcName) {return srcName.replace('.', '/');}}這個類中關鍵方法:
public byte[] transform(final ClassLoader loader, final String classname,final Class<?> classBeingRedefined,final ProtectionDomain protectionDomain,final byte[] classfileBuffer) throws IllegalClassFormatException {// We do not support class retransformation:if (classBeingRedefined != null) {return null;}if (!filter(loader, classname, protectionDomain)) {return null;}try {classFileDumper.dump(classname, classfileBuffer);return instrumenter.instrument(classfileBuffer, classname);} catch (final Exception ex) {final IllegalClassFormatException wrapper = new IllegalClassFormatException(ex.getMessage());wrapper.initCause(ex);// Report this, as the exception is ignored by the JVM:logger.logExeption(wrapper);throw wrapper;}}調用了classFileDumper 類:
/******************************************************************************** Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors* All rights reserved. This program and the accompanying materials* are made available under the terms of the Eclipse Public License v1.0* which accompanies this distribution, and is available at* http://www.eclipse.org/legal/epl-v10.html** Contributors:* Marc R. Hoffmann - initial API and implementation* *******************************************************************************/ package org.jacoco.agent.rt.internal;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream;import org.jacoco.core.internal.data.CRC64;/*** Internal dumper for class files.*/ class ClassFileDumper {private final File location;/*** Create a new dumper for the given location.* * @param location* relative path to dump directory. <code>null</code> if no dumps* should be written*/ClassFileDumper(final String location) {if (location == null) {this.location = null;} else {this.location = new File(location);}}/*** Dumps the given binary content under the given name if a non-* <code>null</code> location has been specified.* * @param name* qualified class name in VM notation* @param contents* binary contents* @throws IOException* in case of problems while dumping the file*/void dump(final String name, final byte[] contents) throws IOException {if (location != null) {final File outputdir;final String localname;final int pkgpos = name.lastIndexOf('/');if (pkgpos != -1) {outputdir = new File(location, name.substring(0, pkgpos));localname = name.substring(pkgpos + 1);} else {outputdir = location;localname = name;}outputdir.mkdirs();final Long id = Long.valueOf(CRC64.classId(contents));final File file = new File(outputdir, String.format("%s.%016x.class", localname, id));final OutputStream out = new FileOutputStream(file);out.write(contents);out.close();}}}這個類將class out 輸出,上面transform方法在調用的時候同時使用:
classFileDumper.dump(classname, classfileBuffer); return instrumenter.instrument(classfileBuffer, classname);final class?InstrSupport類:
public static final String DATAFIELD_DESC = "[Z";// === Init Method ===/*** Name of the initialization method.*/public static final String INITMETHOD_NAME = "$jacocoInit";/*** Descriptor of the initialization method.*/public static final String INITMETHOD_DESC = "()[Z";public static void assertNotInstrumented(final String member,final String owner) throws IllegalStateException {if (member.equals(DATAFIELD_NAME) || member.equals(INITMETHOD_NAME)) {throw new IllegalStateException(format("Class %s is already instrumented.", owner));}}這個類是final 主要作為單例的使用,ClassInstrumenter, ClassAnalyzer調用InstrSupport
ClassAnalyzer 類調用如下:
@Overridepublic MethodProbesVisitor visitMethod(final int access, final String name,final String desc, final String signature, final String[] exceptions) {InstrSupport.assertNotInstrumented(name, coverage.getName());return new MethodAnalyzer(coverage.getName(), coverage.getSuperName(),stringPool.get(name), stringPool.get(desc),stringPool.get(signature), probes, Filters.ALL) {@Overridepublic void visitEnd() {super.visitEnd();final IMethodCoverage methodCoverage = getCoverage();if (methodCoverage.getInstructionCounter().getTotalCount() > 0) {// Only consider methods that actually contain codecoverage.addMethod(methodCoverage);}}};}@Overridepublic FieldVisitor visitField(final int access, final String name,final String desc, final String signature, final Object value) {InstrSupport.assertNotInstrumented(name, coverage.getName());return super.visitField(access, name, desc, signature, value);}public class?ClassInstrumenter?extends ClassProbesVisitor 類;ClassInstrumenter類的調用:
@Overridepublic FieldVisitor visitField(final int access, final String name,final String desc, final String signature, final Object value) {InstrSupport.assertNotInstrumented(name, className);return super.visitField(access, name, desc, signature, value);}@Overridepublic MethodProbesVisitor visitMethod(final int access, final String name,final String desc, final String signature, final String[] exceptions) {InstrSupport.assertNotInstrumented(name, className);final MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);if (mv == null) {return null;}final MethodVisitor frameEliminator = new DuplicateFrameEliminator(mv);final ProbeInserter probeVariableInserter = new ProbeInserter(access,name, desc, frameEliminator, probeArrayStrategy);return new MethodInstrumenter(probeVariableInserter,probeVariableInserter);}
**********?Instrumenter類如下:
從這個類的代碼看,instrument(input,output,string)調用instrument(input,string),后者再調用instrument([],string),再調用instrument(classreader)
所以最終的出口在于最下面的instrument(input,output,string),下面是剩余部分代碼:
public int instrumentAll(final InputStream input, final OutputStream output,final String name) throws IOException {final ContentTypeDetector detector;try {detector = new ContentTypeDetector(input);} catch (final IOException e) {throw instrumentError(name, e);}switch (detector.getType()) {case ContentTypeDetector.CLASSFILE:instrument(detector.getInputStream(), output, name);return 1;case ContentTypeDetector.ZIPFILE:return instrumentZip(detector.getInputStream(), output, name);case ContentTypeDetector.GZFILE:return instrumentGzip(detector.getInputStream(), output, name);case ContentTypeDetector.PACK200FILE:return instrumentPack200(detector.getInputStream(), output, name);default:copy(detector.getInputStream(), output, name);return 0;}}private int instrumentZip(final InputStream input,final OutputStream output, final String name) throws IOException {final ZipInputStream zipin = new ZipInputStream(input);final ZipOutputStream zipout = new ZipOutputStream(output);ZipEntry entry;int count = 0;while ((entry = nextEntry(zipin, name)) != null) {final String entryName = entry.getName();if (signatureRemover.removeEntry(entryName)) {continue;}zipout.putNextEntry(new ZipEntry(entryName));if (!signatureRemover.filterEntry(entryName, zipin, zipout)) {count += instrumentAll(zipin, zipout, name + "@" + entryName);}zipout.closeEntry();}zipout.finish();return count;}private ZipEntry nextEntry(final ZipInputStream input,final String location) throws IOException {try {return input.getNextEntry();} catch (final IOException e) {throw instrumentError(location, e);}}private int instrumentGzip(final InputStream input,final OutputStream output, final String name) throws IOException {final GZIPInputStream gzipInputStream;try {gzipInputStream = new GZIPInputStream(input);} catch (final IOException e) {throw instrumentError(name, e);}final GZIPOutputStream gzout = new GZIPOutputStream(output);final int count = instrumentAll(gzipInputStream, gzout, name);gzout.finish();return count;}private int instrumentPack200(final InputStream input,final OutputStream output, final String name) throws IOException {final InputStream unpackedInput;try {unpackedInput = Pack200Streams.unpack(input);} catch (final IOException e) {throw instrumentError(name, e);}final ByteArrayOutputStream buffer = new ByteArrayOutputStream();final int count = instrumentAll(unpackedInput, buffer, name);Pack200Streams.pack(buffer.toByteArray(), output);return count;}private void copy(final InputStream input, final OutputStream output,final String name) throws IOException {final byte[] buffer = new byte[1024];int len;while ((len = read(input, buffer, name)) != -1) {output.write(buffer, 0, len);}}private int read(final InputStream input, final byte[] buffer,final String name) throws IOException {try {return input.read(buffer);} catch (final IOException e) {throw instrumentError(name, e);}}核心關鍵是instrumentAll這個方法,這個方法根據文件包是class還是zip,或者gz等,不同的加載方式。
jacoco loadclass入口類:CoverageTransformer
核心的兩條代碼:transform?
? ? try{
? ? ? this.classFileDumper.dump(classname, classfileBuffer);
? ? ? return this.instrumenter.instrument(classfileBuffer, classname);
? ? }
**********?具體報錯日志的分析:
java.lang.instrument.IllegalClassFormatException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:93)at sun.instrument.TransformerManager.transform(TransformerManager.java:188)at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)at java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:800)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)at java.net.URLClassLoader.access$100(URLClassLoader.java:71)at java.net.URLClassLoader$1.run(URLClassLoader.java:361)at java.net.URLClassLoader$1.run(URLClassLoader.java:355)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:354)at java.lang.ClassLoader.loadClass(ClassLoader.java:425)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)at java.lang.ClassLoader.loadClass(ClassLoader.java:358)at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:401)at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1432)at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1377)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:641)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:81)at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515)at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:216)at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:143)at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169)at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)at org.testng.TestRunner.privateRun(TestRunner.java:753)at org.testng.TestRunner.run(TestRunner.java:607)at org.testng.SuiteRunner.runTest(SuiteRunner.java:368)at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:363)at org.testng.SuiteRunner.privateRun(SuiteRunner.java:321)at org.testng.SuiteRunner.run(SuiteRunner.java:270)at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)at org.testng.TestNG.runSuitesSequentially(TestNG.java:1284)at org.testng.TestNG.runSuitesLocally(TestNG.java:1209)at org.testng.TestNG.runSuites(TestNG.java:1124)at org.testng.TestNG.run(TestNG.java:1096)at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121) Caused by: java.io.IOException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrumentError(Instrumenter.java:160)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:111)at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:91)... 66 more Caused by: java.lang.IllegalStateException: Class com/suning/srcdas/address/business/AddressBusiness is already instrumented.at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:89)at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)at org.jacoco.agent.rt.internal_6da5971.asm.ClassVisitor.visitField(ClassVisitor.java:272)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.readField(ClassReader.java:768)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:689)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:506)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:84)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:108)... 67 moreat org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:93)at sun.instrument.TransformerManager.transform(TransformerManager.java:188)at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)at java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:800)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)at java.net.URLClassLoader.access$100(URLClassLoader.java:71)at java.net.URLClassLoader$1.run(URLClassLoader.java:361)at java.net.URLClassLoader$1.run(URLClassLoader.java:355)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:354)at java.lang.ClassLoader.loadClass(ClassLoader.java:425)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)at java.lang.ClassLoader.loadClass(ClassLoader.java:358)at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:401)at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1432)at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1377)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:641)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:81)at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515)at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:216)at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:143)at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169)at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)at org.testng.TestRunner.privateRun(TestRunner.java:753)at org.testng.TestRunner.run(TestRunner.java:607)at org.testng.SuiteRunner.runTest(SuiteRunner.java:368)at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:363)at org.testng.SuiteRunner.privateRun(SuiteRunner.java:321)at org.testng.SuiteRunner.run(SuiteRunner.java:270)at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)at org.testng.TestNG.runSuitesSequentially(TestNG.java:1284)at org.testng.TestNG.runSuitesLocally(TestNG.java:1209)at org.testng.TestNG.runSuites(TestNG.java:1124)at org.testng.TestNG.run(TestNG.java:1096)at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121) Caused by: java.io.IOException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrumentError(Instrumenter.java:160)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:111)at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:91)... 66 more Caused by: java.lang.IllegalStateException: Class com/suning/srcdas/address/business/AddressBusiness is already instrumented.at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:89)at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)at org.jacoco.agent.rt.internal_6da5971.asm.ClassVisitor.visitField(ClassVisitor.java:272)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.readField(ClassReader.java:768)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:689)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:506)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:84)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:108)... 67 more?
先要加載一個類,但是這個類的成員聲明了一個對象,所以先使用ClassInstrumenter.visitField 訪問成員,訪問失敗所以為什么
?
打印了Instrumenter.instrument(Instrumenter.java:111)
訪問成員為什么失敗,因為這個成員對象創造之前,需要先加載這個類,然后創建一個類對象,再去創建一個對象的指針。
要加載這個成員對應的類就需要read class ,因為是離線模式(on-offline)所以調用了Instrumenter.instrument? input進來,然后再out出去;覆蓋class文件。
?
總結
以上是生活随笔為你收集整理的jacoco 源码分析 class字节码植入的冲突问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用壁挂炉省还是热水器省
- 下一篇: junit与testng 分别和mock