How to improve the application to avoid problems with a lot of space

I have an application that works pretty much with many user objects that are created inside methods and never need them. The whole structure (in my opinion) is very good object-oriented and uses Services, Utilities and DI-model.

Now that I ran my first “big” tests, I quickly met OutOfMemoryExceptions. Now I do not just want to increase the heap space and do with it, as I can imagine, that this will not solve the problem, but rather delay it until my application becomes larger and encounters the same problem.

I am looking for some simple and easy-to-implement solutions, tips and fragments that help the application deal with garbage collection and heap spaces, especially when it comes to many loops that work with object creation.

Something like "do not create objects in loops, create them before the loop and overwrite it inside" and sorting.

+6
source share
5 answers

I would start by profiling your application and finding memory hotspots using jvisualvm (part of the JDK). This will give you an idea of ​​how large your objects are and what method calls result in high memory usage. He will also tell you how long your objects take in memory, which is usually a good starting point, since you want to zoom out to be as short as possible.

The next step is to identify commonalities in your objects, either by refining your design, or by implementing a cache. If you are loading data from a fixed storage, you can use softreferences, since the JVM ends with a heap, these objects will be GCed (if you make changes to these objects, you will obviously need to transfer them before deleting the hard link). Then, if you need them again, your application just needs to reload them from the backup storage (DB, files or something else).

Make sure you know how the GC works and understands your object references:

  • Strong / direct
  • Soft
  • Weak
  • Phantom

Here are some good articles that explain links and GC:

http://www.java-tips.org/java-se-tips/java.util/using-weakhashmap-for-listener-lists.html

http://pawlan.com/monica/articles/refobjs/

http://www.kdgregory.com/index.php?page=java.refobj

+2
source

Some moments:

  • There is nothing fundamentally wrong with increasing heap space. Different applications have different requirements.
  • Use the profiler to see what is actually happening. For example, here you can find a heap analyzer: MAT
  • When you find that instances of a particular class are responsible for 80% of the heap consumption:
    • try to find a common set of variables with the same values. These are candidates to be one object that can be used by several objects.
    • Make sure you keep some reference to a relatively large graph of objects for a variable that lives much longer than your loops (local variables consume the stack).
    • Let links go beyond as quickly as possible.
    • If you use inner classes, check out those that are not static, since a non-static inner class contains a reference to the containing object.
+5
source

The most important tip I can give you is the same as with any performance issue:

Profile, improve, repeat

Use a profiler (e.g. VisualVM ) to find where the most memory is being consumed. Improve your code, first remove the memory leak, and then reduce the overall memory consumption. Repeat this process until you are satisfied with the quality and performance of your code.

EDIT:

A few trading tricks:

  • Swap objects instead of duplicating whenever possible.

  • Beware of Java class classes (i.e. various implementations of Collection<T> and Map<K,V> ). Depending on what you store and what is used in the collection, you can easily increase memory consumption by an order of magnitude without expecting it.

  • While Java does not (as a rule) have a memory leak in the same sense as in C, Java code often has a problem with objects that are stored until they expire.

    To avoid this, maximize the scope of your links or set them to null when you are done with this object. Note: do not do this with null -setting, especially in trivial methods that are expected to return soon.

    Most importantly: make sure you delete the object from any collections that it could enter when you finish with it. Not doing this is a good recipe for OutOfMemoryError - and the most common reason that people call a memory leak in the Java world.

+4
source

Reset any object reference as soon as the object is no longer needed? Once an object no longer refers to it, GC can assemble it, but I assume you already knew that. GC can also work on raw object graphs (if A has a single link to B and there is no longer a link to A, then you can collect A and B).

It makes no sense to call System.gc (), because if the JVM needs more memory, it will do it on its own, and then use the free memory. If it cannot free up more memory, then you run into OOME.

Now the default heap size is not so large, and therefore quite often a larger heap size is required.

Creating objects in loops is not a particularly bad example, and in many cases it is very relevant. What should be avoided is to repeat an instance of one object in a loop. As a rule, string concatenation should be avoided in loops and replaced with a StringBuilder created outside the loop, since it is much less efficient in terms of performance, but not in terms of memory.

Not sure if I really answer your question.

0
source

Firstly, I would revise my design, focusing on the necessary upper complexity ( designation Landau / Big O ).

Secondly, I would read Josh Bloch Effective Java, paragraph 6 (Eliminate obsolete object references) to learn about

  • common causes of memory leaks
  • rather, using the smallest possible area and then discarding unnecessary objects
  • caching and storage pools.

Third, if you still have OOM exceptions, I will follow Mikko advises .

0
source

Source: https://habr.com/ru/post/909821/


All Articles