Jacoco maven插件阻塞控制台,出现异常-java.lang.IllegalStateException:类已检测

7uzetpgm  于 2023-02-18  发布在  Java
关注(0)|答案(5)|浏览(324)

我正在使用Jacoco插件和power mock mockito组合编写JUnit测试用例来进行声纳代码覆盖,当我运行mvn清洁安装时,所有构建都很顺利,但控制台显示了一个非常长的堆栈跟踪链,该链持续出现在项目中使用的许多类中,这是相当令人恼火的,异常跟踪类似于以下内容-

java.lang.instrument.IllegalClassFormatException: Error while instrumenting class..
Caused by: java.io.IOException: Error while instrumenting class.
Caused by: java.lang.IllegalStateException: Class <class-name> is already instrumented.

我通过下面的链接寻找解决方案,但无法找到出路:-

https://github.com/jacoco/jacoco/issues/32

该链接指出“该错误指示为同一进程配置了两个JaCoCo代理,看起来激活surefire-report-plugin会导致double代理,这不是例外情况,而是测试用JVM配置错误”在我的情况下,我猜甚至不是double agent,因为我的argLine只设置了一个jacoco代理。
在我的例子中,argLine被设置为以下值-

javaagent:C:\\Users\\user\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.7.6.201602180812\\org.jacoco.agent-0.7.6.201602180812-runtime.jar=destfile=C:Users\\user\\git\\package\\target\\jacoco.exec

jacoco-sonar配置的pom.xml条目如下-

<properties>
        <sonar.sources>src/main/java</sonar.sources>
        <sonar.tests>src/test/java</sonar.tests>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <sonar.jacoco.reportPaths>${project.basedir}/target/jacoco.exec</sonar.jacoco.reportPaths>
        <sonar.language>java</sonar.language>
        <sonar.binaries>${project.basedir}/target/classes</sonar.binaries>
        <sonar.inclusions>
            **/com/abc/service/impl/ABCServiceImpl.java,
            **/com/abc/dao/impl/ABCDAOImpl.java
        </sonar.inclusions>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20</version>
                <configuration>
                    <skipTests>false</skipTests>
                    <argLine>-Xmx1024m -XX:MaxPermSize=256m ${argLine}</argLine>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.6.201602180812</version>
                <executions>
                 <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                </execution> 
                <execution>
                    <id>default-instrument</id>
                    <goals>
                        <goal>instrument</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-restore-instrumented-classes</id>
                    <goals>
                        <goal>restore-instrumented-classes</goal>
                    </goals>
                </execution>
                    <execution>
                        <id>default-report</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

注意:如果我删除'default-instrument'和'default-restore-instrumented-classes'的执行元素,则不会出现异常跟踪,但我在声纳 Jmeter 板上获得的覆盖率= 0.0%,使用这两个执行元素给予正确的代码覆盖率,但控制台上的堆栈跟踪很长。如有任何帮助,请予以感谢。

gzszwxb4

gzszwxb41#

根据我对这项研究的见解:JaCoCo Java代理也可以使用离线插装类。在这种情况下,从代理选项中获取配置。必须以排除预插装类的方式配置代理,例如使用“excludes=*“。否则,如果代理再次插装此类,将导致控制台上出现错误消息,就像您的情况一样。
代理jacocoagent.jar是JaCoCo发行版的一部分,包含所有必需的依赖项。可以使用以下JVM选项激活Java代理:

  • -javaagent:[您的路径/]jacocoagent.jar=[选项1]=[值1],[选项2]=[值2]*

有关JaCoCo代理选项,请考虑以下链接:http://www.jacoco.org/jacoco/trunk/doc/agent.html

knpiaxh1

knpiaxh12#

我也遇到过同样的问题,但使用Gradle时遇到过。对我来说,问题在于以下说明

debug {
    testCoverageEnabled true
}

这是我根据一个教程添加的,它也检测类(就像Jacoco做的那样),因此抛出异常。
删除此说明为我解决了问题。

30byixjq

30byixjq3#

我使用Mockito而不是PowerMock,但我不认为与声纳的使用有什么区别,我使用X1 E0 F1 X进行分析,它的工作原理就像一个魅力。
我的pom.xml包含以下属性

<properties>
    <project.source.version>1.8</project.source.version>
    <project.target.version>${project.source.version}</project.target.version>
    <sonar.scanner.version>3.3.0.603</sonar.scanner.version>
    <jacoco.maven.version>0.7.9</jacoco.maven.version>
    <sonar.projectName>MyProject</sonar.projectName>
    <sonar.projectKey>my-project-key</sonar.projectKey>
    <sonar.language>java</sonar.language>
</properties>

插件的配置如下

<plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <inherited>true</inherited>
            <configuration>
                <source>${project.source.version}</source>
                <target>${project.target.version}</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.sonarsource.scanner.maven</groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>${sonar.scanner.version}</version>
        </plugin>

        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.maven.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

您可以使用运行分析

mvn clean install sonar:sonar

这将生成一个位于target/jacoco.exec的默认exec文件,您的本地sonarqube服务器将使用该文件,其中还包含覆盖范围。

更新答复

用powermock测试过了,我用的是powermock jacoco-offline example,只是稍微适应了一下。
那么pom.xml就是

<?xml version="1.0" encoding="UTF-8"?>

http://maven.apache.org/xsd/maven-4.0.0.xsd〉4.0.0版本

<groupId>org.powermock</groupId>
<artifactId>jacoco-offline</artifactId>
<version>1.0.0-SNAPSHOT</version>

<name>JaCoCo Offline with PowerMock</name>
<description>
    Example how to get code coverage with PowerMock
</description>

<properties>
    <jacoco.version>0.7.9</jacoco.version>
    <sonar.scanner.version>3.3.0.603</sonar.scanner.version>
    <!-- Used to locate the profile specific configuration file. -->
    <build.profile.id>dev</build.profile.id>

    <jacoco.it.execution.data.file>${project.build.directory}/coverage-reports/jacoco-it.exec</jacoco.it.execution.data.file>
    <jacoco.ut.execution.data.file>${project.build.directory}/coverage-reports/jacoco-ut.exec</jacoco.ut.execution.data.file>

    <jdk.version>1.8</jdk.version>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <!-- Only unit tests are run by default. -->
    <skip.unit.tests>false</skip.unit.tests>

    <powermock.version>1.7.0</powermock.version>
    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>
    <mockito1.version>1.10.19</mockito1.version>
    <mockito2.version>2.8.9</mockito2.version>
    <easymock.version>3.4</easymock.version>
    <assertj-core.version>3.8.0</assertj-core.version>
    <junit.version>4.12</junit.version>
    <spring.version>3.0.5.RELEASE</spring.version>
    <commons-lang3.version>3.4</commons-lang3.version>

     <sonar.jacoco.reportPaths>${project.basedir}/target/coverage.exec</sonar.jacoco.reportPaths>

</properties>

<dependencies>
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <version>${assertj-core.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jacoco</groupId>
        <artifactId>org.jacoco.agent</artifactId>
        <version>${jacoco.version}</version>
        <classifier>runtime</classifier>
    </dependency>
    <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-core</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito-common</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-support</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4-rule</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-classloading-xstream</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4-rule-agent</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-easymock</artifactId>
            <version>${powermock.version}</version>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-testng</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>${easymock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>${mockito1.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>${jdk.version}</source>
                <target>${jdk.version}</target>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
            <executions>
                <execution>
                    <id>default-instrument</id>
                    <goals>
                        <goal>instrument</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-restore-instrumented-classes</id>
                    <goals>
                        <goal>restore-instrumented-classes</goal>
                    </goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                    <configuration>
                        <dataFile>${project.build.directory}/coverage.exec</dataFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19.1</version>
            <configuration>
                <systemPropertyVariables>
                    <jacoco-agent.destfile>${project.build.directory}/coverage.exec</jacoco-agent.destfile>
                </systemPropertyVariables>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.sonarsource.scanner.maven</groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>${sonar.scanner.version}</version>
        </plugin>
    </plugins>
</build>

这些都是基本的,你是对的,我也错过了覆盖范围。运行mvn clean install后,你可以看到覆盖范围。exec在目标文件夹。默认情况下,声纳正在寻找一个jacoco.exec文件。
您可以调整此行为,只需添加

<sonar.jacoco.reportPaths>${project.basedir}/target/coverage.exec</sonar.jacoco.reportPaths>

在pom.xml中的属性部分。再次运行mvn clean install sonar:sonar后,覆盖范围出现在我的本地sonarqube中。希望这对您有更多帮助...

rdrgkggo

rdrgkggo4#

如果您使用pom.xml和jacoco插件进行构建,那么您需要在构建的“prepare-agent”阶段更新配置,以便排除预先插装的类,如下所示。

<build>
            <plugins>
              <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <executions>
                  <execution>
                <id>default-instrument</id>
                <goals>
                    <goal>instrument</goal>
                </goals>
                  </execution>
                  <execution>
                <id>default-restore-instrumented-classes</id>
                <goals>
                    <goal>restore-instrumented-classes</goal>
                </goals>
                  </execution>
                  <execution>
                <id>prepare-agent</id>
                <goals>
                  <goal>prepare-agent</goal>
                </goals>
                <configuration> 
                <excludes> 
                <exclude>*</exclude> 
                </excludes> 
                </configuration>      
                  </execution>
                  <execution>
                <id>report</id>   
                <goals>
                  <goal>report</goal>
                </goals>
                  </execution>
                </executions>
              </plugin>
            </plugins>
              </build>
wydwbb8l

wydwbb8l5#

这对我有用

debug {
    // disable testCoverage to fix Jacoco instrument error
    testCoverageEnabled false
}

相关问题