Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when a collection in Java increases beyond capacity?

Tags:

java

jvm

I have a service which stages all calls made to it in memory, because we don't want to lose the data and at the same time we need this service to ever fail due to any external dependency (like a DB for example). These staged calls are then routinely picked up and processed in the background.

If, for any reason, if there are too many calls and we run out of memory, we need to be alarmed.

So, the question simply put, is this: What exception do I need to catch or monitor on to notify me when an addition to a list fails due to insufficient resources? Will it result in an OOM in the VM itself, or is there a collection-level limit as well?

If there is no collection-level limit, how would you recommend I monitor the usage of the service? Currently, we have heap usage and memory usage metrics. Are those enough? Also, the JVMs are configured to kill on an OOM error (this is because the VM manager then restarts any process it is managing on a kill).

like image 865
Rohan Prabhu Avatar asked Oct 23 '13 18:10

Rohan Prabhu


3 Answers

The exception to be thrown is OutOfMemoryException. This exception can be thrown in any part of your application, once your collection eats all available heap space.

However if you know that it can be potentially thrown for a specific collection, the best way might be to prevent this to happen, i.e. cap this collection or use caching, so that unused entities are evicted and reloaded on demand. For a lightweight cache implementation I would recommend Guava's CacheBuilder.

UPDATE

Since everybody suggests FS-based storage, here is my lightweight drop-in proposal:

  • CacheBuilder to load your serialized data from NoSQL DB
  • Kryo serializer to convert your objects into byte[]
  • MapDB to store (or any other embedded NoSQL solution you prefer).
like image 181
Andrey Chaschev Avatar answered Sep 28 '22 01:09

Andrey Chaschev


Here's what I found in the specification of Collection.add :

If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after this call returns.

It doesn't specify which exception, so different collections may throw different exceptions.

like image 32
Eran Avatar answered Sep 28 '22 01:09

Eran


I think letting the application fail miserably is not an ideal design choice. You should have threshold on the size of the collection and decide what to do in that case: flush it somewhere (disk?), send a notification (JMX/email), throw an error (or let the OOME propagate).

That said, I'm going to give you a design recommendation. From your brief and slightly cryptic description of the service, it sounds to me like you need a work queue to sit somewhere outside of your service, e.g., a JMS server or even a database. In this way, your background process will be able to pickup the request from the queue (db) and process it even if your service died for any reason.

like image 35
Giovanni Botta Avatar answered Sep 28 '22 00:09

Giovanni Botta