使用 Java 8 构造时创建 Bean 时出现 ArrayOutOfBoundsException

Posted

技术标签:

【中文标题】使用 Java 8 构造时创建 Bean 时出现 ArrayOutOfBoundsException【英文标题】:ArrayOutOfBoundsException on Bean creation while using Java 8 constructs 【发布时间】:2015-08-24 02:22:25 【问题描述】:

当我使用 Java 8 功能时,我在服务启动(创建 Bean)时收到 ArrayIndexOutOfBoundsException

Java 8 已经设置好并且一直在工作。代码编译正确。在服务启动时,服务无法侦听端口,因为没有创建 bean。当我更改代码(删除 java 8 构造)时,服务启动并且一切正常。

这是我正在使用的代码(服务启动的工作代码):

for (Item itemObject : response) 
    if (itemObject.hasId()) 
        idList.add(String.valueOf(itemObject.Id());
    

使用 Java 8 构造的相同代码:

response.parallelStream()
        .filter(itemObject -> itemObject.hasId())
        .map(itemObject -> itemObject.getId())
        .forEach(id -> idList.add(id));

包含这段代码的类的 bean 是使用组件扫描创建的。

以下是使用第二个代码块代替第一个代码块时的异常消息:

Exiting with throwable: java.lang.IllegalArgumentException: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/workspace/.../GetContainerIdForFcSkuAdapter.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 51880
 java.lang.IllegalArgumentException: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/workspace....Some.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 51880

对我来说没有意义的是,为什么在创建 bean 时会覆盖函数内的代码(它不是 bean 类的构造函数)。我问这个,因为当我使用正常的 for 循环而不是并行流时,不存在异常。当调用函数并且实际使用此代码时,不应该出现ArrayOutOfBoundsException

我该如何解决这个问题?

【问题讨论】:

什么是idList?在第二个版本中,您使用的是parallelStream,因此您正在从多个线程将项目添加到此列表中。您使用的列表实现是线程安全的吗?如果您使用stream() 而不是parallelStream(),错误会消失吗? 另外,在列表中获取流内容的正常方法是List<Something> list = stream.collect(Collectors.toList()),而不是stream.forEach(o -> list.add(o) 我并不是真的从多个线程添加。 Java 在内部展开循环并进行并行化。使用蒸汽时仍然存在错误。就像我说的,代码块应该在调用函数时执行,而不是在创建 bean 时执行。如何使用此块并在服务启动时提供 ArrayIndexOutOfBounds。请在下面查看我的答案,并告诉我您是否认为这可能是一个原因 【参考方案1】:

您使用哪个版本的 Spring?您需要升级到 Spring 4 才能使用 Java 8 lambda 表达式。

【讨论】:

是的,4.0.X.RELEASE 使用 java 8. 4.0 还不够。它至少需要 4.0.4 或更高版本。该错误被描述为here 问题 16341【参考方案2】:

我最近在使用 Spring 3.0.5 时发现了一个错误,该错误似乎已在 4.0.5 中修复。以下是详细信息。

如果您的类具有参数化构造函数,并且还具有使用 lambda 表达式的方法(在 Java 8 中引入),则在为该类创建 bean 时会发生 ArrayIndexOutOfException。

【讨论】:

这并不是真正的错误。 Spring 3 不完全支持 Java 8,因此在 Spring 3.0.5 中使用 Lambdas 是用户错误,而不是 Spring 错误。 我刚遇到这个,看起来非常奇怪。正如你所说,当我向 bean 的构造函数添加一个参数时,它就发生了。我在几个地方使用了 forEach。我认为我永远不会建立这样的联系,即类中的任何地方的 forEach 都会以数组边界异常破坏其 bean 实例化。哦,好吧——谢谢,Stack Overflow! 你让我摆脱了噩梦般的头痛!谢谢! 我遇到了同样的问题,但情况有点不同。我的类没有任何参数化构造函数,但在一个函数中使用 lambda 表达式。我尝试将 spring 升级到 v4,但没有帮助。删除 lambda 表达式确实有效。这是一个奇怪的问题!谁能解释为什么会发生这种情况?

以上是关于使用 Java 8 构造时创建 Bean 时出现 ArrayOutOfBoundsException的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring 注入 bean 时出现 nullPointerException

Android - 使用改造时出现错误“无法构造实例(尽管至少存在一个创建)”

Windows Phone 8.1 - 从后台任务创建 WriteableBitmap 时出现异常

创建 EntityManagerFactory 时出现 ArrayIndexOutOfBoundsException

创建 ElasticSearchRepository 时出现 BeanCreationException - 无法解析匹配的构造函数

使用 C# 和 XAML 为 Windows 8.1 创建 facebook 应用程序时出现异常