Bug 291546 - Performance degradation due to usage of Vector in DescriptorEventManager

Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com>
Reviewed-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/AddressDescriptorEventListener.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/AddressDescriptorEventListener.java
index 0d25d3a..a7bf0b8 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/AddressDescriptorEventListener.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/AddressDescriptorEventListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,12 +9,17 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.models.events;
 
-import java.util.Vector;
-import org.eclipse.persistence.descriptors.*;
-import org.eclipse.persistence.testing.framework.*;
+import java.util.List;
+
+import org.eclipse.persistence.descriptors.DescriptorEvent;
+import org.eclipse.persistence.descriptors.DescriptorEventListener;
+import org.eclipse.persistence.descriptors.DescriptorEventManager;
+import org.eclipse.persistence.testing.framework.TestErrorException;
 
 public class AddressDescriptorEventListener implements DescriptorEventListener {
     public boolean preInsertExecuted;
@@ -60,7 +65,8 @@ public void checkRowEvent(DescriptorEvent event) {
         }
     }
 
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector eventManagers) {
+    @Override
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         return false;
     }
 
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/CustomerDescriptorEventListener.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/CustomerDescriptorEventListener.java
index 2c2512a..3224524 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/CustomerDescriptorEventListener.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/CustomerDescriptorEventListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,12 +9,17 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.models.events;
 
-import java.util.Vector;
-import org.eclipse.persistence.descriptors.*;
-import org.eclipse.persistence.queries.*;
+import java.util.List;
+
+import org.eclipse.persistence.descriptors.DescriptorEvent;
+import org.eclipse.persistence.descriptors.DescriptorEventListener;
+import org.eclipse.persistence.descriptors.DescriptorEventManager;
+import org.eclipse.persistence.queries.ObjectLevelModifyQuery;
 
 public class CustomerDescriptorEventListener implements DescriptorEventListener {
     public void aboutToInsert(DescriptorEvent event) {
@@ -26,7 +31,8 @@ public void aboutToDelete(DescriptorEvent event) {
     public void aboutToUpdate(DescriptorEvent event) {
     }
 
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector eventManagers) {
+    @Override
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         return false;
     }
 
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/Phone.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/Phone.java
index 2bad9ed..13c3a04 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/Phone.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/events/Phone.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,11 +9,17 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.models.events;
 
-import java.util.Vector;
-import org.eclipse.persistence.descriptors.*;
+import java.util.List;
+
+import org.eclipse.persistence.descriptors.DescriptorEvent;
+import org.eclipse.persistence.descriptors.DescriptorEventListener;
+import org.eclipse.persistence.descriptors.DescriptorEventManager;
+import org.eclipse.persistence.descriptors.RelationalDescriptor;
 import org.eclipse.persistence.tools.schemaframework.TableDefinition;
 
 public class Phone implements DescriptorEventListener {
@@ -84,7 +90,8 @@ public static Phone example2() {
         return phone;
     }
 
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector eventManagers) {
+    @Override
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         return false;
     }
 
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/events/EventHookTestCase.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/events/EventHookTestCase.java
index 276bd7f..40fc253 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/events/EventHookTestCase.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/events/EventHookTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,6 +9,8 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.tests.events;
 
@@ -70,6 +72,6 @@ public void setup() {
         setEmailAccount(EmailAccount.example1());
         setPhoneNumber(Phone.example1());
         setAddress(Address.example1());
-        setAddressListener((AddressDescriptorEventListener)getSession().getDescriptor(Address.class).getEventManager().getEventListeners().firstElement());
+        setAddressListener((AddressDescriptorEventListener)getSession().getDescriptor(Address.class).getEventManager().getEventListeners().get(0));
     }
 }
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/nondeferredwrites/EmployeeDescriptorEventListener.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/nondeferredwrites/EmployeeDescriptorEventListener.java
index 2c5d0cb..40ee049 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/nondeferredwrites/EmployeeDescriptorEventListener.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/nondeferredwrites/EmployeeDescriptorEventListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,14 +9,17 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.tests.nondeferredwrites;
 
-import java.util.Vector;
+import java.util.List;
 
 import org.eclipse.persistence.descriptors.DescriptorEvent;
 import org.eclipse.persistence.descriptors.DescriptorEventListener;
-import org.eclipse.persistence.testing.framework.*;
+import org.eclipse.persistence.descriptors.DescriptorEventManager;
+import org.eclipse.persistence.testing.framework.TestErrorException;
 
 public class EmployeeDescriptorEventListener implements DescriptorEventListener {
     public boolean postInsertExecuted = false;
@@ -102,7 +105,8 @@ public void preWrite(DescriptorEvent event) {
      * Implementers should define this method if they need or want to restrict
      * the calling of inherited events.
      */
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector eventManagers) {
+    @Override
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         return false;
     }
 
diff --git a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/workbenchintegration/EventListenerCollectionTest.java b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/workbenchintegration/EventListenerCollectionTest.java
index 9cca417..c3604f6 100644
--- a/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/workbenchintegration/EventListenerCollectionTest.java
+++ b/foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/workbenchintegration/EventListenerCollectionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,17 +9,22 @@
  *
  * Contributors:
  *     John Vandale - initial API and implementation
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.testing.tests.workbenchintegration;
 
 import java.io.File;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.eclipse.persistence.descriptors.ClassDescriptor;
-import org.eclipse.persistence.testing.models.employee.relational.EmployeeProject;
+import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
+import org.eclipse.persistence.descriptors.DescriptorEventListener;
 import org.eclipse.persistence.sessions.factories.XMLProjectReader;
 import org.eclipse.persistence.sessions.factories.XMLProjectWriter;
-import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
 import org.eclipse.persistence.testing.models.employee.domain.Employee;
+import org.eclipse.persistence.testing.models.employee.relational.EmployeeProject;
 
 /**
  * Bug 295383
@@ -53,11 +58,11 @@ public void verify() {
         ClassDescriptor descriptor =
             project.getDescriptors().get(Employee.class);
 
-        java.util.Vector listeners = descriptor.getEventManager().getEventListeners();
+        List<DescriptorEventListener> listeners = descriptor.getEventManager().getEventListeners();
 
         //test that the collection type is a NonSynchronizedVector
-        if (!(listeners instanceof org.eclipse.persistence.internal.helper.NonSynchronizedVector)) {
-            throwError("Descriptor from project XML with event listeners does not use NonSynchronizedVector for event listeners collection.");
+        if (!(listeners instanceof CopyOnWriteArrayList)) {
+            throwError("Descriptor from project XML with event listeners does not use CopyOnWriteArrayList for event listeners collection.");
         }
     }
 
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventAdapter.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventAdapter.java
index 8707cd1..2ad94c5 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventAdapter.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventAdapter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,10 +9,12 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.descriptors;
 
-import java.util.Vector;
+import java.util.List;
 
 /**
  * <p><b>Purpose</b>: Provides an empty implementation of DescriptorEventListener.
@@ -29,7 +31,8 @@ public void aboutToUpdate(DescriptorEvent event) {}
 
     public void aboutToDelete(DescriptorEvent event) {}
 
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector<DescriptorEventManager> eventManagers) {
+    @Override
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         return false;
     }
 
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventListener.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventListener.java
index f5ac180..b9b6664 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventListener.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,10 +9,13 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.descriptors;
 
-import java.util.*;
+import java.util.EventListener;
+import java.util.List;
 
 /**
  * <p><b>Purpose</b>: Used to support Java event listener event model on descriptors.
@@ -34,14 +37,14 @@ public interface DescriptorEventListener extends EventListener {
      * This event can be used to amend an object's delete row.
      */
     // CR#2660080 was missing aboutToDelete
-    public void aboutToDelete(DescriptorEvent event);
+    void aboutToDelete(DescriptorEvent event);
 
     /**
      * This event is raised before a new object is inserted to the database.
      * The object's row has already been built and is accessible from the event.
      * This event can be used to amend an object's insert row.
      */
-    public void aboutToInsert(DescriptorEvent event);
+    void aboutToInsert(DescriptorEvent event);
 
     /**
      * This event is raised before an object is updated in the database.
@@ -49,19 +52,19 @@ public interface DescriptorEventListener extends EventListener {
      * The object's row has already been built and is accessible from the event.
      * This event can be used to amend an object's update row.
      */
-    public void aboutToUpdate(DescriptorEvent event);
+    void aboutToUpdate(DescriptorEvent event);
 
     /**
      * Implementers should define this method if they need or want to restrict
      * the calling of inherited events.
      */
-     public boolean isOverriddenEvent(DescriptorEvent event, Vector<DescriptorEventManager> eventManagers);
+    boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers);
 
     /**
      * This event is raised after an object is built from its row on a read operation.
      * This event can be used to initialize non-persistent or non-mapped state in the object.
      */
-    public void postBuild(DescriptorEvent event);
+    void postBuild(DescriptorEvent event);
 
     /**
      * This event is raised after an object is cloned into a unit of work.
@@ -69,17 +72,17 @@ public interface DescriptorEventListener extends EventListener {
      * The event source/object is the unit of work clone,
      * the event originalObject is the original object from the session cache.
      */
-    public void postClone(DescriptorEvent event);
+    void postClone(DescriptorEvent event);
 
     /**
      * This event is raised after an object is deleted from the database.
      */
-    public void postDelete(DescriptorEvent event);
+    void postDelete(DescriptorEvent event);
 
     /**
      * This event is raised after an object is inserted to the database.
      */
-    public void postInsert(DescriptorEvent event);
+    void postInsert(DescriptorEvent event);
 
     /**
      * This event is raised after an object is merged from a unit of work into its parent.
@@ -87,46 +90,46 @@ public interface DescriptorEventListener extends EventListener {
      * The event source/object is the parent session object that was merged into,
      * the event originalObject is the unit of work clone that was merged from.
      */
-    public void postMerge(DescriptorEvent event);
+    void postMerge(DescriptorEvent event);
 
     /**
      * This event is raised after an object is refreshed from its row on a refresh operation.
      * This event can be used to initialize non-persistent or non-mapped state in the object.
      */
-    public void postRefresh(DescriptorEvent event);
+    void postRefresh(DescriptorEvent event);
 
     /**
      * This event is raised after an object updated in the database.
      * This event is only raised for objects that had changes and were updated.
      */
-    public void postUpdate(DescriptorEvent event);
+    void postUpdate(DescriptorEvent event);
 
     /**
      * This event is raised after an object is inserted or updated in the database.
      * This event is only raised for new objects or objects that had changes and were updated.
      */
-    public void postWrite(DescriptorEvent event);
+    void postWrite(DescriptorEvent event);
 
     /**
      * This event is raised before an object is deleted from the database.
      */
-    public void preDelete(DescriptorEvent event);
+    void preDelete(DescriptorEvent event);
 
     /**
      * This event is raised before an object is inserted to the database.
      */
-    public void preInsert(DescriptorEvent event);
+    void preInsert(DescriptorEvent event);
 
     /**
      * This event is only raised by the EntityManager.  It is raised when the
      * create operation is initiated on an object.
      */
-    public void prePersist(DescriptorEvent event);
+    void prePersist(DescriptorEvent event);
 
     /**
      * This event is raised when the remove operation is initiated on an object.
      */
-    public void preRemove(DescriptorEvent event);
+    void preRemove(DescriptorEvent event);
 
     /**
      * This event is raised for all existing objects written or committed in a unit of work.
@@ -134,7 +137,7 @@ public interface DescriptorEventListener extends EventListener {
      * so the object may still be modified by the event.
      * If the object has no changes, it will not be updated in a unit of work.
      */
-    public void preUpdate(DescriptorEvent event);
+    void preUpdate(DescriptorEvent event);
 
     /**
      * This event is raised before an object is updated regardless if the object
@@ -143,7 +146,7 @@ public interface DescriptorEventListener extends EventListener {
      * event. For objects that have database changes, an aboutToUpdate will also
      * be triggered.
      */
-    public void preUpdateWithChanges(DescriptorEvent event);
+    void preUpdateWithChanges(DescriptorEvent event);
 
     /**
      * This event is raised for all new or existing objects written or committed in a unit of work.
@@ -151,5 +154,6 @@ public interface DescriptorEventListener extends EventListener {
      * so the object may still be modified by the event.
      * If the object is existing and has no changes, it will not be updated in a unit of work.
      */
-    public void preWrite(DescriptorEvent event);
+    void preWrite(DescriptorEvent event);
+
 }
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventManager.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventManager.java
index 1df87f7..a15eb45 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventManager.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEventManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -9,6 +9,8 @@
  *
  * Contributors:
  *     Oracle - initial API and implementation from Oracle TopLink
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.descriptors;
 
@@ -19,13 +21,13 @@
 import java.security.PrivilegedActionException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Vector;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicReferenceArray;
 
 import org.eclipse.persistence.core.descriptors.CoreDescriptorEventManager;
 import org.eclipse.persistence.exceptions.DescriptorException;
 import org.eclipse.persistence.internal.helper.ClassConstants;
 import org.eclipse.persistence.internal.helper.Helper;
-import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
 import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
 import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
 import org.eclipse.persistence.internal.sessions.AbstractSession;
@@ -54,29 +56,29 @@
  */
 public class DescriptorEventManager extends CoreDescriptorEventManager<DescriptorEvent> implements Cloneable, Serializable {
     protected ClassDescriptor descriptor;
-    protected Vector eventSelectors;
-    protected transient Vector eventMethods;
-    protected transient Vector eventListeners;
+    protected AtomicReferenceArray<String> eventSelectors;
+    protected transient AtomicReferenceArray<Method> eventMethods;
+    protected transient List<DescriptorEventListener> eventListeners;
 
     // EJB 3.0 support for event listeners.
-    protected transient Vector defaultEventListeners;
-    protected transient Vector entityListenerEventListeners;
+    protected transient List<DescriptorEventListener> defaultEventListeners;
+    protected transient List<DescriptorEventListener> entityListenerEventListeners;
     protected transient DescriptorEventListener entityEventListener;
     /**
      * Listeners that are fired after all other listeners are fired
      */
-    protected transient List<DescriptorEventListener>  internalListeners = new ArrayList<DescriptorEventListener>();
+    protected transient List<DescriptorEventListener>  internalListeners = new ArrayList<>();
 
     // EJB 3.0 support - cache our parent event managers.
-    protected transient Vector entityEventManagers;
-    protected transient Vector entityListenerEventManagers;
+    protected transient List<DescriptorEventManager> entityEventManagers;
+    protected transient List<DescriptorEventManager> entityListenerEventManagers;
 
     // EJB 3.0 support for event listener configuration flags.
     protected boolean excludeDefaultListeners;
     protected boolean excludeSuperclassListeners;
 
     //JPA project caching support.  Holds DescriptorEventListener representations for serialization/storage.
-    protected java.util.List<SerializableDescriptorEventHolder> descriptorEventHolders;
+    protected List<SerializableDescriptorEventHolder> descriptorEventHolders;
 
     /** PERF: Cache if any events listener exist. */
     protected boolean hasAnyEventListeners;
@@ -103,22 +105,18 @@ public class DescriptorEventManager extends CoreDescriptorEventManager<Descripto
     public static final int PreRemoveEvent = 16;
     public static final int PreUpdateWithChangesEvent = 17;
 
-   protected static final int NumberOfEvents = 18;
+    protected static final int NumberOfEvents = 18;
+
     /**
      * INTERNAL:
      * Returns a new DescriptorEventManager for the specified ClassDescriptor.
      */
     public DescriptorEventManager() {
-        this.eventSelectors = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(NumberOfEvents);
-        this.eventMethods = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(NumberOfEvents);
+        this.eventSelectors = newAtomicReferenceArray(NumberOfEvents);
+        this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
         this.hasAnyEventListeners = false;
         this.excludeDefaultListeners = false;
         this.excludeSuperclassListeners = false;
-
-        for (int index = 0; index < NumberOfEvents; index++) {
-            this.eventSelectors.addElement(null);
-            this.eventMethods.addElement(null);
-        }
     }
 
     /**
@@ -126,7 +124,7 @@ public DescriptorEventManager() {
      * EJB 3.0 support for default listeners.
      */
     public void addDefaultEventListener(DescriptorEventListener listener) {
-        getDefaultEventListeners().addElement(listener);
+        getDefaultEventListeners().add(listener);
     }
 
     /**
@@ -135,7 +133,7 @@ public void addDefaultEventListener(DescriptorEventListener listener) {
      * listener class.
      */
     public void addEntityListenerEventListener(DescriptorEventListener listener) {
-        getEntityListenerEventListeners().addElement(listener);
+        getEntityListenerEventListeners().add(listener);
     }
 
     /**
@@ -144,7 +142,7 @@ public void addEntityListenerEventListener(DescriptorEventListener listener) {
      * when an event occurs on any instance of the descriptor's class.
      */
     public void addListener(DescriptorEventListener listener) {
-        getEventListeners().addElement(listener);
+        getEventListeners().add(listener);
         setHasAnyEventListeners(true);
     }
 
@@ -154,7 +152,7 @@ public void addListener(DescriptorEventListener listener) {
      */
     public void addInternalListener(DescriptorEventListener listener) {
         if (internalListeners==null) {
-            internalListeners = new ArrayList<DescriptorEventListener>();
+            internalListeners = new ArrayList<>();
         }
         internalListeners.add(listener);
         setHasAnyEventListeners(true); // ensure that events are generated
@@ -176,8 +174,8 @@ public void addEntityListenerHolder(SerializableDescriptorEventHolder holder) {
     public Object clone() {
         try {
             DescriptorEventManager clone = (DescriptorEventManager)super.clone();
-            clone.setEventSelectors((Vector)getEventSelectors().clone());
-            clone.setEventMethods((Vector)getEventMethods().clone());
+            clone.setEventSelectors(newAtomicReferenceArray(getEventSelectors()));
+            clone.setEventMethods(newAtomicReferenceArray(getEventMethods()));
             clone.setEventListeners(getEventListeners());
             return clone;
         } catch (Exception exception) {
@@ -238,7 +236,7 @@ public void executeEvent(DescriptorEvent event) throws DescriptorException {
                 return;
             }
 
-            Method eventMethod = (Method)getEventMethods().elementAt(event.getEventCode());
+            Method eventMethod = (Method)getEventMethods().get(event.getEventCode());
             if (eventMethod == null) {
                 return;
             }
@@ -281,7 +279,7 @@ public void executeEvent(DescriptorEvent event) throws DescriptorException {
     protected Method findMethod(int selector) throws DescriptorException {
         Class[] declarationParameters = new Class[1];
         declarationParameters[0] = ClassConstants.DescriptorEvent_Class;
-        String methodName = (String)getEventSelectors().elementAt(selector);
+        String methodName = getEventSelectors().get(selector);
 
         try {
             return Helper.getDeclaredMethod(getDescriptor().getJavaClass(), methodName, declarationParameters);
@@ -297,32 +295,31 @@ protected Method findMethod(int selector) throws DescriptorException {
      * bug 251180 - Missing method org.eclipse.persistence.descriptors.DescriptorEventManager#setAboutToDeleteSelector
      */
     public String getAboutToDeleteSelector() {
-        return (String)getEventSelectors().elementAt(AboutToDeleteEvent);
+        return getEventSelectors().get(AboutToDeleteEvent);
     }
 
     /**
      * INTERNAL:
      */
     public String getAboutToInsertSelector() {
-        return (String)getEventSelectors().elementAt(AboutToInsertEvent);
+        return getEventSelectors().get(AboutToInsertEvent);
     }
 
     /**
      * INTERNAL:
      */
     public String getAboutToUpdateSelector() {
-        return (String)getEventSelectors().elementAt(AboutToUpdateEvent);
+        return getEventSelectors().get(AboutToUpdateEvent);
     }
 
     /**
      * INTERNAL:
      * EJB 3.0 support. Returns the default listeners.
      */
-    public Vector getDefaultEventListeners() {
+    public List<DescriptorEventListener> getDefaultEventListeners() {
         if (defaultEventListeners == null) {
-            defaultEventListeners = new NonSynchronizedVector();
+            defaultEventListeners = new CopyOnWriteArrayList<>();
         }
-
         return defaultEventListeners;
     }
 
@@ -338,9 +335,9 @@ protected ClassDescriptor getDescriptor() {
      * used by JPA project caching to store DescriptorEventListener representations that can build the underlying
      * DescriptorEventListener and add it to the EventManager.
      */
-    public java.util.List<SerializableDescriptorEventHolder> getDescriptorEventHolders() {
+    public List<SerializableDescriptorEventHolder> getDescriptorEventHolders() {
         if (descriptorEventHolders == null) {
-            descriptorEventHolders = new java.util.ArrayList();
+            descriptorEventHolders = new CopyOnWriteArrayList<>();
         }
         return descriptorEventHolders;
     }
@@ -350,7 +347,7 @@ public java.util.List<SerializableDescriptorEventHolder> getDescriptorEventHolde
      * used by JPA project caching to store DescriptorEventListener representations that can build the underlying
      * DescriptorEventListener and add it to the EventManager.
      */
-    public void setDescriptorEventHolders(java.util.List<SerializableDescriptorEventHolder> descriptorEventHolders) {
+    public void setDescriptorEventHolders(List<SerializableDescriptorEventHolder> descriptorEventHolders) {
         this.descriptorEventHolders = descriptorEventHolders;
     }
 
@@ -366,11 +363,10 @@ public DescriptorEventListener getEntityEventListener() {
      * INTERNAL:
      * EJB 3.0 support. Returns the entity listener event listeners.
      */
-    public Vector getEntityListenerEventListeners() {
+    public List<DescriptorEventListener> getEntityListenerEventListeners() {
         if (entityListenerEventListeners == null) {
-            entityListenerEventListeners = new Vector();
+            entityListenerEventListeners = new CopyOnWriteArrayList<>();
         }
-
         return entityListenerEventListeners;
     }
 
@@ -380,31 +376,25 @@ public Vector getEntityListenerEventListeners() {
      *
      * @see #addListener(DescriptorEventListener)
      */
-    public Vector getEventListeners() {
+    public List<DescriptorEventListener> getEventListeners() {
         // Lazy initialize to avoid unnecessary enumerations.
         if (eventListeners == null) {
-            eventListeners = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
+            eventListeners = new CopyOnWriteArrayList<>();
         }
         return eventListeners;
     }
 
-    protected Vector getEventMethods() {
+    protected AtomicReferenceArray<Method> getEventMethods() {
         //Lazy Initialized to prevent Null Pointer exception after serialization
         if (this.eventMethods == null) {
-            this.eventMethods = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(NumberOfEvents);
-            for (int index = 0; index < NumberOfEvents; ++index) {
-                this.eventMethods.addElement(null);
-            }
+            this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
         }
         return eventMethods;
     }
 
-    protected Vector getEventSelectors() {
+    protected AtomicReferenceArray<String> getEventSelectors() {
         if (this.eventSelectors == null) {
-            this.eventSelectors = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(NumberOfEvents);
-            for (int index = 0; index < NumberOfEvents; ++index) {
-                this.eventSelectors.addElement(null);
-            }
+            this.eventSelectors = newAtomicReferenceArray(NumberOfEvents);
         }
         return eventSelectors;
     }
@@ -414,7 +404,7 @@ protected Vector getEventSelectors() {
      *  The name of the method called after an object is built
      */
     public String getPostBuildSelector() {
-        return (String)getEventSelectors().elementAt(PostBuildEvent);
+        return getEventSelectors().get(PostBuildEvent);
     }
 
     /**
@@ -422,7 +412,7 @@ public String getPostBuildSelector() {
      *  The name of the method called after an object is cloned
      */
     public String getPostCloneSelector() {
-        return (String)getEventSelectors().elementAt(PostCloneEvent);
+        return getEventSelectors().get(PostCloneEvent);
     }
 
     /**
@@ -430,7 +420,7 @@ public String getPostCloneSelector() {
      *  The name of the method called after an object is deleted
      */
     public String getPostDeleteSelector() {
-        return (String)getEventSelectors().elementAt(PostDeleteEvent);
+        return getEventSelectors().get(PostDeleteEvent);
     }
 
     /**
@@ -438,7 +428,7 @@ public String getPostDeleteSelector() {
      *  The name of the method called after an object is inserted
      */
     public String getPostInsertSelector() {
-        return (String)getEventSelectors().elementAt(PostInsertEvent);
+        return getEventSelectors().get(PostInsertEvent);
     }
 
     /**
@@ -446,7 +436,7 @@ public String getPostInsertSelector() {
      *  The name of the method called after an object is merged
      */
     public String getPostMergeSelector() {
-        return (String)getEventSelectors().elementAt(PostMergeEvent);
+        return getEventSelectors().get(PostMergeEvent);
     }
 
     /**
@@ -454,7 +444,7 @@ public String getPostMergeSelector() {
      *  The name of the method called after an object is refreshed
      */
     public String getPostRefreshSelector() {
-        return (String)getEventSelectors().elementAt(PostRefreshEvent);
+        return getEventSelectors().get(PostRefreshEvent);
     }
 
     /**
@@ -462,7 +452,7 @@ public String getPostRefreshSelector() {
      *  The name of the method called after an object is updated
      */
     public String getPostUpdateSelector() {
-        return (String)getEventSelectors().elementAt(PostUpdateEvent);
+        return getEventSelectors().get(PostUpdateEvent);
     }
 
     /**
@@ -470,7 +460,7 @@ public String getPostUpdateSelector() {
      *  The name of the method called after an object is written
      */
     public String getPostWriteSelector() {
-        return (String)getEventSelectors().elementAt(PostWriteEvent);
+        return getEventSelectors().get(PostWriteEvent);
     }
 
     /**
@@ -478,7 +468,7 @@ public String getPostWriteSelector() {
      *  The name of the method called before the create operation is applied to an object
      */
     public String getPrePersistSelector() {
-        return (String)getEventSelectors().elementAt(PrePersistEvent);
+        return getEventSelectors().get(PrePersistEvent);
     }
 
   /**
@@ -486,7 +476,7 @@ public String getPrePersistSelector() {
      *  The name of the method called before an object is deleted
      */
     public String getPreDeleteSelector() {
-        return (String)getEventSelectors().elementAt(PreDeleteEvent);
+        return getEventSelectors().get(PreDeleteEvent);
     }
 
     /**
@@ -494,7 +484,7 @@ public String getPreDeleteSelector() {
      *  The name of the method called before an object is inserted
      */
     public String getPreInsertSelector() {
-        return (String)getEventSelectors().elementAt(PreInsertEvent);
+        return getEventSelectors().get(PreInsertEvent);
     }
 
     /**
@@ -502,7 +492,7 @@ public String getPreInsertSelector() {
      *  The name of the method called before the remove operation is applied to an object
      */
     public String getPreRemoveSelector() {
-        return (String)getEventSelectors().elementAt(PreRemoveEvent);
+        return getEventSelectors().get(PreRemoveEvent);
     }
 
   /**
@@ -510,7 +500,7 @@ public String getPreRemoveSelector() {
      *  The name of the method called before an object is updated
      */
     public String getPreUpdateSelector() {
-        return (String)getEventSelectors().elementAt(PreUpdateEvent);
+        return getEventSelectors().get(PreUpdateEvent);
     }
 
     /**
@@ -518,7 +508,7 @@ public String getPreUpdateSelector() {
      *  The name of the method called before an object is written
      */
     public String getPreWriteSelector() {
-        return (String)getEventSelectors().elementAt(PreWriteEvent);
+        return getEventSelectors().get(PreWriteEvent);
     }
 
     /**
@@ -563,7 +553,7 @@ public boolean hasEntityEventListener() {
      * listener event listeners.
      */
     public boolean hasInternalEventListeners() {
-        return internalListeners != null && internalListeners.size() > 0;
+        return internalListeners != null && !internalListeners.isEmpty();
     }
 
     /**
@@ -572,7 +562,7 @@ public boolean hasInternalEventListeners() {
      * listener event listeners.
      */
     public boolean hasEntityListenerEventListeners() {
-        return entityListenerEventListeners != null && entityListenerEventListeners.size() > 0;
+        return entityListenerEventListeners != null && !entityListenerEventListeners.isEmpty();
     }
 
     /**
@@ -592,10 +582,11 @@ public void initialize(AbstractSession session) {
             setHasAnyEventListeners(true);
         }
 
+        final AtomicReferenceArray<String> selectors = getEventSelectors();
         for (int index = 0; index < NumberOfEvents; index++) {
-            if (getEventSelectors().elementAt(index) != null) {
+            if (selectors.get(index) != null) {
                 setHasAnyEventListeners(true);
-                getEventMethods().setElementAt(findMethod(index), index);
+                getEventMethods().set(index, findMethod(index));
             }
         }
 
@@ -608,9 +599,9 @@ public void initialize(AbstractSession session) {
             }
 
             for (int index = 0; index < NumberOfEvents; index++) {
-                if ((getEventSelectors().get(index) == null) && (parentEventManager.getEventSelectors().get(index) != null)) {
+                if ((selectors.get(index) == null) && (parentEventManager.getEventSelectors().get(index) != null)) {
                     setHasAnyEventListeners(true);
-                    getEventSelectors().set(index, parentEventManager.getEventSelectors().get(index));
+                    selectors.set(index, parentEventManager.getEventSelectors().get(index));
                     getEventMethods().set(index, parentEventManager.getEventMethods().get(index));
                 }
             }
@@ -624,8 +615,8 @@ public void initialize(AbstractSession session) {
      * once.
      */
     protected void initializeEJB30EventManagers() {
-        entityEventManagers = new NonSynchronizedVector();
-        entityListenerEventManagers = new NonSynchronizedVector();
+        entityEventManagers = new CopyOnWriteArrayList<>();
+        entityListenerEventManagers = new CopyOnWriteArrayList<>();
 
         if (hasEntityEventListener()) {
             entityEventManagers.add(this);
@@ -672,7 +663,7 @@ protected void notifyEJB30Listeners(DescriptorEvent event) {
 
         // Step 2 - Notify the Entity Listener's first, top -> down.
         for (int index = entityListenerEventManagers.size() - 1; index >= 0; index--) {
-            Vector entityListenerEventListeners = ((DescriptorEventManager) entityListenerEventManagers.get(index)).getEntityListenerEventListeners();
+            List entityListenerEventListeners = ((DescriptorEventManager) entityListenerEventManagers.get(index)).getEntityListenerEventListeners();
 
             for (int i = 0; i < entityListenerEventListeners.size(); i++) {
                 DescriptorEventListener listener = (DescriptorEventListener) entityListenerEventListeners.get(i);
@@ -683,7 +674,7 @@ protected void notifyEJB30Listeners(DescriptorEvent event) {
         // Step 3 - Notify the Entity event listeners. top -> down, unless
         // they are overridden in a subclass.
         for (int index = entityEventManagers.size() - 1; index >= 0; index--) {
-            DescriptorEventListener entityEventListener = ((DescriptorEventManager) entityEventManagers.get(index)).getEntityEventListener();
+            DescriptorEventListener entityEventListener = entityEventManagers.get(index).getEntityEventListener();
 
             if (! entityEventListener.isOverriddenEvent(event, entityEventManagers)) {
                 notifyListener(entityEventListener, event);
@@ -786,12 +777,7 @@ public void notifyListeners(DescriptorEvent event) {
      * Used to initialize a remote DescriptorEventManager.
      */
     public void remoteInitialization(AbstractSession session) {
-        this.eventMethods = new Vector(NumberOfEvents);
-
-        for (int index = 0; index < NumberOfEvents; index++) {
-            this.eventMethods.addElement(null);
-        }
-
+        this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
         initialize(session);
     }
 
@@ -800,7 +786,7 @@ public void remoteInitialization(AbstractSession session) {
      * Remove a event listener.
      */
     public void removeListener(DescriptorEventListener listener) {
-        getEventListeners().removeElement(listener);
+        getEventListeners().remove(listener);
     }
 
     /**
@@ -813,7 +799,7 @@ public void removeListener(DescriptorEventListener listener) {
      */
     //bug 251180: Missing method org.eclipse.persistence.descriptors.DescriptorEventManager#setAboutToDeleteSelector
     public void setAboutToDeleteSelector(String aboutToDeleteSelector) {
-        getEventSelectors().setElementAt(aboutToDeleteSelector, AboutToDeleteEvent);
+        getEventSelectors().set(AboutToDeleteEvent, aboutToDeleteSelector);
     }
 
     /**
@@ -825,7 +811,7 @@ public void setAboutToDeleteSelector(String aboutToDeleteSelector) {
      * insert, such as adding a user inserted by.
      */
     public void setAboutToInsertSelector(String aboutToInsertSelector) {
-        getEventSelectors().setElementAt(aboutToInsertSelector, AboutToInsertEvent);
+        getEventSelectors().set(AboutToInsertEvent, aboutToInsertSelector);
     }
 
     /**
@@ -838,7 +824,7 @@ public void setAboutToInsertSelector(String aboutToInsertSelector) {
      * to modify the row before insert, such as adding a user inserted by.
      */
     public void setAboutToUpdateSelector(String aboutToUpdateSelector) {
-        getEventSelectors().setElementAt(aboutToUpdateSelector, AboutToUpdateEvent);
+        getEventSelectors().set(AboutToUpdateEvent, aboutToUpdateSelector);
     }
 
     /**
@@ -857,15 +843,19 @@ public void setEntityEventListener(DescriptorEventListener listener) {
         this.entityEventListener = listener;
     }
 
-    protected void setEventListeners(Vector eventListeners) {
-        this.eventListeners = eventListeners;
+    protected void setEventListeners(List<DescriptorEventListener> eventListeners) {
+        if (eventListeners instanceof CopyOnWriteArrayList) {
+            this.eventListeners = eventListeners;
+        } else {
+            this.eventListeners = new CopyOnWriteArrayList(eventListeners);
+        }
     }
 
-    protected void setEventMethods(Vector eventMethods) {
+    protected void setEventMethods(AtomicReferenceArray<Method> eventMethods) {
         this.eventMethods = eventMethods;
     }
 
-    protected void setEventSelectors(Vector eventSelectors) {
+    protected void setEventSelectors(AtomicReferenceArray<String> eventSelectors) {
         this.eventSelectors = eventSelectors;
     }
 
@@ -909,7 +899,7 @@ protected void setHasAnyEventListeners(boolean hasAnyEventListeners) {
      * mappings. This event is called whenever an object is built.
      */
     public void setPostBuildSelector(String postBuildSelector) {
-        getEventSelectors().setElementAt(postBuildSelector, PostBuildEvent);
+        getEventSelectors().set(PostBuildEvent, postBuildSelector);
     }
 
     /**
@@ -920,7 +910,7 @@ public void setPostBuildSelector(String postBuildSelector) {
      * to correctly initialize an object's non-persistent attributes.
      */
     public void setPostCloneSelector(String postCloneSelector) {
-        getEventSelectors().setElementAt(postCloneSelector, PostCloneEvent);
+        getEventSelectors().set(PostCloneEvent, postCloneSelector);
     }
 
     /**
@@ -930,7 +920,7 @@ public void setPostCloneSelector(String postCloneSelector) {
      * on the object.
      */
     public void setPostDeleteSelector(String postDeleteSelector) {
-        getEventSelectors().setElementAt(postDeleteSelector, PostDeleteEvent);
+        getEventSelectors().set(PostDeleteEvent, postDeleteSelector);
     }
 
     /**
@@ -941,7 +931,7 @@ public void setPostDeleteSelector(String postDeleteSelector) {
      * the object has been inserted.
      */
     public void setPostInsertSelector(String postInsertSelector) {
-        getEventSelectors().setElementAt(postInsertSelector, PostInsertEvent);
+        getEventSelectors().set(PostInsertEvent, postInsertSelector);
     }
 
     /**
@@ -953,7 +943,7 @@ public void setPostInsertSelector(String postInsertSelector) {
      * initialize an object's non-persistent attributes.
      */
     public void setPostMergeSelector(String postMergeSelector) {
-        getEventSelectors().setElementAt(postMergeSelector, PostMergeEvent);
+        getEventSelectors().set(PostMergeEvent, postMergeSelector);
     }
 
     /**
@@ -965,7 +955,7 @@ public void setPostMergeSelector(String postMergeSelector) {
      * mappings. This event is only called on refreshes of existing objects.
      */
     public void setPostRefreshSelector(String postRefreshSelector) {
-        getEventSelectors().setElementAt(postRefreshSelector, PostRefreshEvent);
+        getEventSelectors().set(PostRefreshEvent, postRefreshSelector);
     }
 
     /**
@@ -974,7 +964,7 @@ public void setPostRefreshSelector(String postRefreshSelector) {
      * updated into the database.
      */
     public void setPostUpdateSelector(String postUpdateSelector) {
-        getEventSelectors().setElementAt(postUpdateSelector, PostUpdateEvent);
+        getEventSelectors().set(PostUpdateEvent, postUpdateSelector);
     }
 
     /**
@@ -988,7 +978,7 @@ public void setPostUpdateSelector(String postUpdateSelector) {
      * event can be used to notify any dependent on the object.
      */
     public void setPostWriteSelector(String postWriteSelector) {
-        getEventSelectors().setElementAt(postWriteSelector, PostWriteEvent);
+        getEventSelectors().set(PostWriteEvent, postWriteSelector);
     }
 
     /**
@@ -998,7 +988,7 @@ public void setPostWriteSelector(String postWriteSelector) {
      * on the object.
      */
     public void setPreDeleteSelector(String preDeleteSelector) {
-        getEventSelectors().setElementAt(preDeleteSelector, PreDeleteEvent);
+        getEventSelectors().set(PreDeleteEvent, preDeleteSelector);
     }
 
     /**
@@ -1009,7 +999,7 @@ public void setPreDeleteSelector(String preDeleteSelector) {
      * mechanism.
      */
     public void setPreInsertSelector(String preInsertSelector) {
-        getEventSelectors().setElementAt(preInsertSelector, PreInsertEvent);
+        getEventSelectors().set(PreInsertEvent, preInsertSelector);
     }
 
     /**
@@ -1018,7 +1008,7 @@ public void setPreInsertSelector(String preInsertSelector) {
      * the create operation applied to it.
      */
     public void setPrePersistSelector(String prePersistSelector) {
-        getEventSelectors().setElementAt(prePersistSelector, PrePersistEvent);
+        getEventSelectors().set(PrePersistEvent, prePersistSelector);
     }
 
     /**
@@ -1027,7 +1017,7 @@ public void setPrePersistSelector(String prePersistSelector) {
      * the remove operation applied to it.
      */
     public void setPreRemoveSelector(String preRemoveSelector) {
-        getEventSelectors().setElementAt(preRemoveSelector, PreRemoveEvent);
+        getEventSelectors().set(PreRemoveEvent, preRemoveSelector);
     }
 
     /**
@@ -1040,7 +1030,7 @@ public void setPreRemoveSelector(String preRemoveSelector) {
      * any dependent on the object.
      */
     public void setPreUpdateSelector(String preUpdateSelector) {
-        getEventSelectors().setElementAt(preUpdateSelector, PreUpdateEvent);
+        getEventSelectors().set(PreUpdateEvent, preUpdateSelector);
     }
 
     /**
@@ -1054,6 +1044,32 @@ public void setPreUpdateSelector(String preUpdateSelector) {
      * event can be used to notify any dependent on the object.
      */
     public void setPreWriteSelector(String preWriteSelector) {
-        getEventSelectors().setElementAt(preWriteSelector, PreWriteEvent);
+        getEventSelectors().set(PreWriteEvent, preWriteSelector);
     }
+
+    /**
+     * Create an instance of {@link AtomicIntegerArray} initialized with {@code NullEvent} values.
+     *
+     * @param length length of the array.
+     * @return initialized instance of {@link AtomicIntegerArray}
+     */
+    private static <T> AtomicReferenceArray<T> newAtomicReferenceArray(final int length) {
+        final AtomicReferenceArray array = new AtomicReferenceArray<>(length);
+        for (int index = 0; index < length; array.set(index++, null));
+        return (AtomicReferenceArray<T>)array;
+    }
+
+    /**
+     * Create an instance of {@link AtomicIntegerArray} initialized with content of provided array.
+     *
+     * @param src source array.
+     * @return initialized instance of {@link AtomicIntegerArray}
+     */
+    private static <T> AtomicReferenceArray<T> newAtomicReferenceArray(final AtomicReferenceArray<T> src) {
+        final int length = src.length();
+        final AtomicReferenceArray array = new AtomicReferenceArray<>(length);
+        for (int index = 0; index < length; array.set(index, src.get(index++)));
+        return (AtomicReferenceArray<T>)array;
+    }
+
 }
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/EntityListener.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/EntityListener.java
index f8d2845..465b0dd 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/EntityListener.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/EntityListener.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -14,6 +14,8 @@
  *       - 211324: Add additional event(s) support to the EclipseLink-ORM.XML Schema
  *     07/15/2010-2.2 Guy Pelletier
  *       -311395 : Multiple lifecycle callback methods for the same lifecycle event
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.metadata.listeners;
 
@@ -25,10 +27,9 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.persistence.descriptors.DescriptorEvent;
 import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
@@ -62,8 +63,8 @@ public class EntityListener<T> extends DescriptorEventAdapter {
     private T m_listener;
     private Class<T> m_listenerClass;
     private Class m_entityClass;
-    private Hashtable<String, List<Method>> m_methods;
-    private Hashtable<String, Hashtable<Integer, Boolean>> m_overriddenEvents;
+    private Map<String, List<Method>> m_methods;
+    private final Map<String, Map<Integer, Boolean>> m_overriddenEvents;
     private static final Map<Integer, String> m_eventStrings;
     private AbstractSession owningSession;
 
@@ -86,11 +87,11 @@ public class EntityListener<T> extends DescriptorEventAdapter {
      */
     protected EntityListener(Class entityClass) {
         m_entityClass = entityClass;
-        m_methods = new Hashtable<>();
+        m_methods = new ConcurrentHashMap<>();
 
         // Remember which events are overridden in subclasses. Overridden events
         // must be built for each subclass chain.
-        m_overriddenEvents = new Hashtable<>();
+        m_overriddenEvents = new ConcurrentHashMap<>();
     }
 
     public EntityListener(Class<T> listenerClass, Class entityClass){
@@ -178,14 +179,14 @@ public Class getEntityClass() {
     /**
      * INTERNAL:
      */
-    public Hashtable<String, List<Method>> getAllEventMethods() {
+    public Map<String, List<Method>> getAllEventMethods() {
         return m_methods;
     }
 
     /**
      * INTERNAL:
      */
-    public void setAllEventMethods(Hashtable<String, List<Method>> methods) {
+    public void setAllEventMethods(Map<String, List<Method>> methods) {
         m_methods = methods;
     }
 
@@ -201,12 +202,7 @@ public void setOwningSession(AbstractSession owningSession) {
      */
     protected List<Method> getEventMethods(int eventCode) {
         String eventString = m_eventStrings.get(eventCode);
-
-        if (eventString != null) {
-            return getEventMethods(eventString);
-        } else {
-            return null;
-        }
+        return eventString != null ? getEventMethods(eventString) : null;
     }
 
     /**
@@ -356,14 +352,14 @@ void invokeMethod(String event, DescriptorEvent descriptorEvent) {
      * overridden in a subclass.
      */
     @Override
-    public boolean isOverriddenEvent(DescriptorEvent event, Vector<DescriptorEventManager> eventManagers) {
+    public boolean isOverriddenEvent(DescriptorEvent event, List<DescriptorEventManager> eventManagers) {
         int eventCode = event.getEventCode();
         String forSubclass = event.getDescriptor().getJavaClassName();
-        Hashtable<Integer, Boolean> subClassMap = m_overriddenEvents.get(forSubclass);
+        Map<Integer, Boolean> subClassMap = m_overriddenEvents.get(forSubclass);
 
         // If we haven't built an overridden events map for this subclass, do so now.
         if (subClassMap == null) {
-            subClassMap = new Hashtable<>();
+            subClassMap = new ConcurrentHashMap<>();
         }
 
         // Now check the individual events for this subclass.
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/JPAEntityListenerHolder.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/JPAEntityListenerHolder.java
index 00c88ee..a488d90 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/JPAEntityListenerHolder.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/listeners/JPAEntityListenerHolder.java
@@ -11,6 +11,8 @@
  *     Oracle - initial API and implementation
  *     08/01/2012-2.5 Chris Delahunt
  *       - 371950: Metadata caching
+ *     12/14/2017-3.0 Tomas Kraus
+ *       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.metadata.listeners;
 
@@ -18,8 +20,9 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.persistence.descriptors.ClassDescriptor;
 import org.eclipse.persistence.descriptors.DescriptorEventListener;
@@ -37,7 +40,7 @@ public class JPAEntityListenerHolder implements SerializableDescriptorEventHolde
 
     public transient DescriptorEventListener listener;
 
-    public java.util.Hashtable<String,java.util.List<MethodSerialImpl>> serializableMethods;
+    public Map<String,java.util.List<MethodSerialImpl>> serializableMethods;
 
     public void setIsDefaultListener(Boolean isDefaultListener) {
         this.isDefaultListener = isDefaultListener;
@@ -108,8 +111,8 @@ protected Object clone() throws CloneNotSupportedException {
         return super.clone();
     }
 
-    public void convertToSerializableMethods(java.util.Hashtable<String,java.util.List<Method>> methods) {
-        this.serializableMethods = new java.util.Hashtable();
+    public void convertToSerializableMethods(Map<String,java.util.List<Method>> methods) {
+        this.serializableMethods = new ConcurrentHashMap<>();
         for (String event: methods.keySet()){
             java.util.List<Method> methodList = methods.get(event);
             java.util.List<MethodSerialImpl> newMethodList = new java.util.ArrayList();
@@ -168,8 +171,8 @@ public void addEventMethod(String event, Method method) {
      * @param loader
      * @return
      */
-    public java.util.Hashtable<String,java.util.List<Method>> convertToMethods(ClassLoader loader) {
-        java.util.Hashtable<String,java.util.List<Method>> table = new java.util.Hashtable();
+    public Map<String,java.util.List<Method>> convertToMethods(ClassLoader loader) {
+        Map<String,java.util.List<Method>> table = new ConcurrentHashMap<>();
         for (String event: serializableMethods.keySet()){
             java.util.List<MethodSerialImpl> methodList = serializableMethods.get(event);
             java.util.List<Method> newMethodList = new java.util.ArrayList();
@@ -186,9 +189,9 @@ public java.util.Hashtable<String,java.util.List<Method>> convertToMethods(Class
         return table;
     }
 
-    public java.util.Hashtable<String,java.util.List<MethodSerialImpl>> getMethods() {
+    public Map<String,java.util.List<MethodSerialImpl>> getMethods() {
         if (serializableMethods == null) {
-            serializableMethods = new Hashtable<String, List<MethodSerialImpl>>();
+            serializableMethods = new ConcurrentHashMap<String, List<MethodSerialImpl>>();
         }
         return serializableMethods;
     }