Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentModificationException偶尔出现_Java_Multithreading - Fatal编程技术网

Java ConcurrentModificationException偶尔出现

Java ConcurrentModificationException偶尔出现,java,multithreading,Java,Multithreading,我有一个JavaSE库和对源代码的完全访问权限,当无状态EJB在负载测试期间执行时,源代码偶尔会抛出ConcurrentModificationException 应用服务器在JDK 11.0.2上运行 最初,异常发生在封送处理期间,类似于,但我添加了对以下方法的调用,以查看异常也可能发生在何处: private static Object deepCopy(Object object) { try { ByteArrayOutputStream

我有一个JavaSE库和对源代码的完全访问权限,当无状态EJB在负载测试期间执行时,源代码偶尔会抛出ConcurrentModificationException

应用服务器在JDK 11.0.2上运行

最初,异常发生在封送处理期间,类似于,但我添加了对以下方法的调用,以查看异常也可能发生在何处:

    private static Object deepCopy(Object object) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutputStream outputStrm = new ObjectOutputStream(outputStream);
            outputStrm.writeObject(object); // line 164 in MyClass
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream objInputStream = new ObjectInputStream(inputStream);
            return objInputStream.readObject();
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
以下是异常的Stacktrace示例:

java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList.writeObject(ArrayList.java:900)
    at java.base/jdk.internal.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1130)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
    at com.my.java.se.library.MyClass.deepCopy(MyClass.java:164)
    at com.my.java.se.library.MyClass.someMethod(MyClass.java:132)
    at com.my.thorntail.app.SomeStatelessEJB.callToSeLib(SomeStatelessEJB.java:50)
   ....
我在一些方法中增加了对深度拷贝的调用,而且例外有时发生在某些方法的末尾,有时在中间某个地方。 我不知道我应该从中得出什么结论。是否有其他线程决定要修改对象

现在,整个JavaSE库不包含任何关于线程的语句,因此它是纯单线程的。据我所知,在单个线程中发生ConcurrentModificationException的唯一可能的选择是,在对数组进行迭代时对其进行修改。然而,情况并非如此

这种例外可能还有什么其他原因? 我怎样才能找出哪里出了问题

根据Kayaman的回答进行编辑:

JavaSE库实际上也是我们开发的代码的一部分,因此调用代码和库代码都可能是罪魁祸首

我从使用deepCopy方法的实验中得出结论,错误就在那里。deepCopy方法导致库中抛出ConcurrentModificationException。但这可能是错误的

下面是调用代码的结构,它在负载测试期间同时在多个线程中运行。在试图将代码简化为基本部分时,我意识到了一个可能的问题:

@Stateless
public class SomeStatelessEJB {

   private MyClass myClass;

   public void callToSeLib() {
      myClass = getMyClassInstance(); // we are reusing the same MyClass object !!
      myClass.someMethod();
   }

}
我将调整代码以不再重用此对象,然后在这里报告

编辑以报告进度

这确实是MyClass对象的重用

修复方法是只重用MyClass对象的部分,而为每个请求创建部分和重新创建廉价且有问题的部分的成本很高


谢谢你强迫我把代码压缩到最低限度来解释这里的情况。在这个过程中,我注意到了错误。

stacktrace告诉您,在某个点上,您正在序列化一个ArrayList,同时它也在被修改。ArrayList中的相关代码

因此,要么您有来自不同线程的对象被变异,要么您已经设法编写代码,使列表通过不同的方式在同一线程中变异。在单线程的情况下,如果元素有自己的writeObject修改列表,就有可能得到这个结果。当然,在代码中这样做是很可怕的

你说这个库不使用线程,但是你仍然在基于你的环境使用线程,所以我们现在还不想给出最简单的解释

也许你应该展示一下你是如何调用MyClass.someMethod的,因为这是你的代码,而且这总是第一个疑点,在责怪你自己之前不要责怪库

    // Write out element count, and any hidden stuff
    int expectedModCount = modCount;
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
        s.writeObject(elementData[i]);
    }

    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }