【问题标题】:Always getting exception "Wrong type at constant pool index" with Cucumber-Java8使用 Cucumber-Java8 总是出现异常“常量池索引处的类型错误”
【发布时间】:2015-09-22 22:56:19
【问题描述】:

我正在尝试为 Cucumber 的 Java8 方言建立一个示例项目。我的问题是,我没有让它运行。我总是得到以下异常层次结构:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.068 sec <<< FAILURE! - in soy.wimmer.CucumberIT
Feature: Cucumber with Java8  Time elapsed: 0.051 sec  <<< ERROR!
cucumber.runtime.CucumberException: Failed to instantiate class soy.wimmer.CucumberStepdefs
[…]
Caused by: java.lang.reflect.InvocationTargetException: null
[…]
Caused by: cucumber.runtime.CucumberException: java.lang.IllegalArgumentException: Wrong type at constant pool index
[…]
Caused by: java.lang.IllegalArgumentException: Wrong type at constant pool index
    at sun.reflect.ConstantPool.getMemberRefInfoAt0(Native Method)
    at sun.reflect.ConstantPool.getMemberRefInfoAt(ConstantPool.java:47)
    at cucumber.runtime.java8.ConstantPoolTypeIntrospector.getTypeString(ConstantPoolTypeIntrospector.java:37)
    at cucumber.runtime.java8.ConstantPoolTypeIntrospector.getGenericTypes(ConstantPoolTypeIntrospector.java:27)
    at cucumber.runtime.java.Java8StepDefinition.<init>(Java8StepDefinition.java:45)
    at cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:162)
    at cucumber.api.java8.En.Given(En.java:190)
    at soy.wimmer.CucumberStepdefs.<init>(CucumberStepdefs.java:8)
[…]

Results :

Tests in error: 
  Failed to instantiate class soy.wimmer.CucumberStepdefs

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0

我不知道为什么会出现此错误,也不知道如何解决。

我已将所有内容打包在一个 Maven 项目中。布局是这样的:

./src/test/java/soy/wimmer/CucumberIT.java
./src/test/java/soy/wimmer/CucumberStepdefs.java
./src/test/resources/cucumber/cucumber-java8.feature
./pom.xml

我在 pom.xml 中包含的依赖项是:

<dependencies>                                                               
    <dependency>                                                             
        <groupId>info.cukes</groupId>                                        
        <artifactId>cucumber-java8</artifactId>                              
        <version>1.2.3</version>                                             
        <scope>test</scope>                                                  
    </dependency>                                                            

    <dependency>                                                             
        <groupId>info.cukes</groupId>                                        
        <artifactId>cucumber-junit</artifactId>                              
        <version>1.2.3</version>                                             
        <scope>test</scope>                                                  
    </dependency>                                                            

    <dependency>                                                             
        <groupId>junit</groupId>                                             
        <artifactId>junit</artifactId>                                       
        <version>4.12</version>                                              
        <scope>test</scope>                                                  
    </dependency>                                                            
</dependencies>

另外,pom.xml 只加载编译器和故障安全插件。

我对 CucumberIT.java 的定义:

package soy.wimmer;                                                              

import cucumber.api.CucumberOptions;                                             
import cucumber.api.junit.Cucumber;                                              
import org.junit.runner.RunWith;                                                 

@RunWith(Cucumber.class)                                                         
@CucumberOptions(features = "classpath:cucumber")                                
public class CucumberIT {                                                        
}        

我的特征定义:

Feature: Cucumber with Java8                                                     
        As a developer                                                           
        I want to use Cucumber-java8                                             
        So that I have nicer step definitions                                    

        Scenario: Let's try it                                                   
                Given I have some dummy code                                     
                When I try to test it                                            
                Then it should work with cucumber-java8  

这是我的步骤定义:

package soy.wimmer;                                                              

import cucumber.api.PendingException;                                            
import cucumber.api.java8.En;                                                    

public class CucumberStepdefs implements En {                                    
    public CucumberStepdefs() {                                                  
        Given("^I have some dummy code$", () -> {                                
            // Write code here that turns the phrase above into concrete actions 
            throw new PendingException();                                        
        });                                                                      

        When("^I try to test it$", () -> {                                       
            // Write code here that turns the phrase above into concrete actions 
            throw new PendingException();                                        
        });                                                                      

        Then("^it should work with cucumber-java(\\d+)$", (Integer arg1) -> {    
            // Write code here that turns the phrase above into concrete actions 
            throw new PendingException();                                        
        });                                                                      
    }                                                                            
}

知道我在这里做错了什么吗?

【问题讨论】:

  • 嗯,异常消息缺少实际类型,但我猜它的类型 18this answer 适用。简而言之,Cucumber 似乎不适合 Java 8,实际上,它甚至不是 100% 兼容 Java 7……
  • 可能是 Invokedynamic,因为类的构造函数中有 lambda 表达式。但是我已经将编译器配置为 pom.xml 中的源和目标版本 1.8,它是步骤定义,因此是本地编译的类,不是吗?
  • 正如链接答案中所说,问题是不是编译器。问题是有一个 runtime 工具试图处理编译的类文件,也就是字节码。看看抛出IllegalArgumentException的方法。
  • @Holger 好的,现在我明白你的意思了。但它似乎也在特殊的 java8 代码中被调用。 (我现在在我的问题中添加了部分堆栈跟踪。)我已经尝试阅读导致异常的代码,但我不明白;-)
  • 我们看到 Cucumber 正在戳入 Java 的私有类,即 sun.reflect.ConstantPool,这是导致兼容性问题的秘诀,但查看 the offending line 会变得更糟。大哎哟。谁能假设常量池的任意位置(大小 - 2)包含特定信息?这高度依赖于编译器,即使使用相同的编译器也不能保证这些项目的任何特定顺序。

标签: java-8 cucumber bdd cucumber-jvm cucumber-java


【解决方案1】:

问题是因为Cucumber的Java8方言使用了Oracle的JDK8的实现细节。

我使用的是由 Debian 打包的 OpenJDK8,这导致了常量池的不同组织。当我尝试使用 Oracle 的 JDK8 时,一切都按预期工作。

如果你想自己尝试,我在github上发布了完整的示例项目:https://github.com/mawis/cucumber-java8-test

我还在 cucumber-jvm 的问题跟踪器上报告了一个错误:https://github.com/cucumber/cucumber-jvm/issues/912

您可以查看问题跟踪器,看看问题是否会在未来得到解决。

现在如果你想使用 cucumber-java8 似乎你必须使用 Oracle 的 JDK 实现。

(解决这个问题的名声属于Holger,他的问题是他的问题。我只是想把这个答案写成一个总结。)

【讨论】:

  • 因此,如果我没看错的话,只要我使用 Oracle 的 JDK,我应该会看到它工作正常。但是,我得到与原始海报完全相同的错误。我正在使用 Java 版本 1.8.0_60,作为 Oracle JDK 的一部分下载。
  • 这似乎也取决于您使用的JDK版本。 Oracle 最近的 JDK 似乎也不能正常工作。
【解决方案2】:

只需使用最近发布的1.2.5 版本。它解决了接受的答案引用的错误。

【讨论】:

    猜你喜欢
    • 2015-11-08
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多