Issue #950: NullPointerException when using multithreading

Type: Bug ReoprtPriority: NormalStatus: FixedReplies: 8
#1

[ObjectDB 2.4.4_08] Unexpected exception (Error 990)
  Generated by Java HotSpot(TM) Client VM 1.6.0_29 (on Windows 7 6.1).

Please report this error on http://www.objectdb.com/database/issue/new
com.objectdb.o.InternalException: java.lang.NullPointerException: null
java.lang.NullPointerException
at com.objectdb.o.ENT.C(ENT.java:557)
at com.objectdb.o.OBM.bz(OBM.java:385)
at com.objectdb.o.OBM.bz(OBM.java:261)
at com.objectdb.jpa.EMImpl.persist(EMImpl.java:377)
at ...

When running object DB in Server mode, I have numerous threads trying to concurrently persist new entities to the database.  When the client application starts writing, several of the threads throw the above exception but most of the threads are able to do their writes without issue. 

#2

This exception is thrown during an attempt to persist an entity.

Could you please provide more information about the entity object and its type?

The exception may indicate a non entity type. Is it an entity type?

Is it a new object that wasn't managed by ObjectDB before?

ObjectDB Support
#3

Here is the entity declaration with all its embedded types:

@Entity
public class MyEntity {

    @Id private int firstId;
    @Id private String secondId;

    @OneToOne(cascade=CascadeType.ALL)
    private HashMap<String, EmbeddableA> myMap;

}

@Embeddable
public class EmbeddableA {

    @OneToOne(cascade=CascadeType.ALL)
    private HashMap<String, EmbeddableB> myMap;

}

@Embeddable
public class EmbeddableB {

    @OneToOne(cascade=CascadeType.ALL)
    private HashMap<String, Object> myMap;

}

I'm am trying to do an evaluation and want to store 200 million entities in the database.  I have a temporary key and have activated the license.  My application is persisting about 1000 of these each second from among 500 active threads.  Between each persist, the thread sleeps for half a second.  The database blows up with the exception provided after anywhere from 100,000 persists to 1.5 million commits.  The client application has a single instance of the EntityManagerFactory and each thread has its own instance of EntityManager.  After 500 persists, the thread calls a flush() on the database. 

To my knowledge the entity and embedded classes are annotated correctly.  EmbeddableB is just storing primitive integers in its map.  However it will also be used to store String, and Joda DateTime.  However the test code at this time is just storing the integers. 

#4

Your model looks fine. Please provide a test that demonstrates the problem.

ObjectDB Support
#5

I have attached a test application that exposes the problem.  I've also attached a text file that demonstrates the output when executing the attached program.  The test application is a simple Eclipse project.  You can import the project and then attach your instance of the objectdb jar.  The test application will add one million unique entities to the database.  Based on the implementation, you will need to delete the odb file between each execution of the application.

#6

Thank you for the test program and for this report. There was a missing synchronized causing problems when a new persistent type is used simultaneously from several threads.

Please try build 2.4.4_10 that should solve this issue.

By the way, writing performance may be improved by:

  • Enhancing the code.
  • Using embedded mode instead of client server mode.
  • Persisting bulk of objects every transaction (instead of a transaction per entity object).
ObjectDB Support
#7

Thank you for your prompt customer support.  The 2.4.4_10 version provided did help with the issue however the original issue still exists.  The good news is that the application runs much longer before seeing its first exception.  I've attached the output from the test application for your review.  Please advise.

#8

This time it seems that the problem is in the test:

    threadPoolExecutor.shutdown();
    threadPoolExecutor.awaitTermination(3, TimeUnit.MINUTES);
    factory.close();

After 3 minutes the EntityManagerFactory is closed with all its EntityManager instances, but there are still running tasks that use EntityManager instances.

ObjectDB Support
#9

Good catch!  ObjectDB is performing very well now that I have adjusted my executor and allowed for enough time for the worker threads to do their thing.  Thank you again for your support.

Reply