`

Java Memory Leaks et al. (2. Act)

阅读更多

The first act of this blog-series Java OutOfMemoryError – A tragedy in seven acts described the architecture of JVM memory and discussed where a java.lang.OutOfMemoryError could occur.

So let’s have a detailed look on how this error can actually happen in a Java application.

In the previous post, we saw multiple possible types of the OutOfMemoryError. But the one happening most of the time is this one:

Exception in thread "main": java.lang.OutOfMemoryError: Java heap space

The error indicates that there has not been enough free heap to fulfill an allocation request for a new object. In other words: there is no room for the object on the heap. Since, according to the JVM specification, every heap has to have a garbage collector, this also means that no memory was freeable by it. So the whole memory is filled with “live” objects.

To understand how this can happen, it is important to understand what a “live” object actually is.

In Java objects get generated on the heap and live on as long as they are referenced. The garbage collector checks during it GC-phases if the object is still referenced – and does mark it as “garbage” and clean it up later when this is no longer the case (the actual behaviour differs for different gc-algorithms, like the Copying Collectors or Garbage-First, but is not of importance for understanding liveness). But not every reference is important for surviving, but only so called GC root references. Especially when understanding Memory Leaks, GC roots are a central concept to identify the important references to an object. Garbage Collector Roots are special objects which do not have incoming references and are responsible for keeping referenced objects alive. When an object cannot be reached directly or indirectly from a GC root, it will be marked as “unreachable” and made eligible for garbage collection. Simply speaking, there are three kinds of GC roots:

• Temporary variables on the stack of a thread

• Static members of a loaded class

• Special native references from JNI

Here an example which shows where GC Roots play a role for a class:

public class MyFrame extends javax.swing.JFrame {
 
  // reachable via Classloader as soon class is loaded
  public static final ArrayList STATIC = new ArrayList();
 
  // as long as the JFrame is not dispose()'d,
  // it is reachable via a native window
  private final ArrayList jni = new ArrayList()
 
  // while this method is executing parameter is kept reachable,
  // even if it is not used
  private void myMethod(ArrayList parameter) {
 
    // while this method is running, this list is reachable from the stack
    ArrayList local = new ArrayList();
  }
 
}

Usually there are tree types of issues with Java OutOfMemoryError problems in heap memory:

  • Objects, which can be reached via a GC root reference, but are actually no longer used by application code. Those are called Java Memory Leaks.
  • Too many or too large objects. So there is not enough heap available for the application to execute. Usually happens when there are large objects kept in cache like structures.
  • Too many temporary objects. So there is just for a short time not enough memory. Usually happens in load scenarios where many temporary objects are used.

Java Memory Leaks

So Java Memory Leaks occur when objects still have a GC root reference, but are not actually used anymore. Those “Loitering Objects” stay around for the whole life of the JVM. If the application is creating those “dead objects” on and on, the memory will be filled up and eventually result in a java.lang.OutOfMemoryError. Typical causes are static collections, which are used as a kind of cache. Usually objects are added, but never removed (Let’s face it: How often have you used add() and put() and how often used remove() methods?). Because the objects are referenced by the static collection, they cannot be freed up anymore, as the collection has a GC root reference via the classloader.

When discussing Memory Leaks one comes usually across the terms dominator or dominator tree. The dominator concept comes from graph theory and defines a node as dominator of another node when this node can only be reached via it. Applying this to memory management, object A is dominator for object B when there is no object C which holds a reference to B. A dominator tree is a partial tree in which this condition holds true for all nodes from the root node. When the root reference is freed, the whole dominator tree is freed as well. Large dominator trees are great candidates when looking for memory leaks.

Depending on the creation frequency and the object size, as well as the size of the Java heap, the OutOfMemoryError occurs sooner or later. Especially those “creeping memory leaks” can be found in many applications, but are usually “ignored” by:

  • Using large heaps to delay the error. Happens frequently nowadays, as the old 32bit memory limit has vanished through the usage of 64 bit JVMs.
  • Restarting the application server during the night. This “resets” the memory usage. If the memory leak takes longer than 24 hours to become severe, this will help.

But both variants are dangerous, as they have negative impact on the system performance and are heavily influenced by the system usage. A change in usage or more “traffic” can produce the error faster than expected. Garbage collection times also have a negative effect on the application performance, as the increasing “tenured generation” causes longer “Mark”-Phases during garbage collection, resulting in longer pause times, which can be observed as system hangs. Act 3 and 4 will describe analysis of those leaks in details and give advice on how to avoid them.

Too much memory

Besides Java memory leaks, there are is another reason for OutOfMemoryError: The application is just consuming too much memory. Either there is not enough heap configured and it has to be increased (also see part 3 of the series) or the consumption has to be throtteled, e.g. by shrinking cache sizes.

Especially critical is high temporary memory usage in enterprise applications, which can have a high number of concurrent users. Because it can happen out of the blue, this OutOfMemoryError is especially troublesome, as it cannot be countered with a nightly reboot. The following code illustrates the problem:

byte[] image = getTheByteImage();
response.setContentType("image/jpeg");
ServletOutputStream out = response.getOutputStream();
out.write(image);
out.flush();
out.close();

While it is not that obvious, the code consumes memory on heap for each image before sending it to the browser. A much better variant would be to stream the image like this:

InputStream image = getTheImageAsStream();
response.setContentType("image/jpeg");
ServletOutputStream out = response.getOutputStream();
IOUtils.copy(image, out);
out.flush();
out.close();

(Of course BufferedStreams and IOUtils use byte[] internally as well, but this is much smaller)

Having covered only the java.lang.OutOfMemoryError problems in heap, I might dedicate another post to other areas, like the permanent generation as mentioned in the previous episode.

The next episode will be “Confguring and Monitoring the Java Virtual Machine”, which will show how to configure and optimize the Sun JVM and how to monitor it with the bundled tools.

“Creating and understanding Java Heapdumps“ will then be the fourth episode and describe how to handle Heapdumps. We will find out how to discover the causes of the Memory Leaks described here.

Also those two are going to be more practical oriented, so you can expect some screencasts.

分享到:
评论

相关推荐

    Detected memory leaks简单检测方法

    ### Detected Memory Leaks 简单检测方法 #### 背景介绍 在软件开发过程中,内存泄漏是一个常见的问题,特别是在使用C/C++等需要手动管理内存的语言进行开发时更为突出。内存泄漏不仅会导致程序占用的内存持续增长...

    论文研究-A Tool for Testing Java Memory Leaks.pdf

    标题《论文研究-A Tool for Testing Java Memory Leaks.pdf》和描述《一个测试Java内存泄漏的工具,党万春,钱巨,虽然Java语言有自带的垃圾回收机制,Java程序仍然存在由无效引用带来的内存泄漏。而内存泄漏会导致...

    MemoryAnalyzer-1.7.0.20170613-macosx.cocoa.x86_64.zip

    The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption. Use the Memory Analyzer to analyze productive heap dumps with...

    ML-Leaks-master.zip

    2. **攻击策略**:攻击者可能采用多种策略来区分训练样本和测试样本,如比较模型对不同样本的预测概率、分析梯度信息等。代码将展示这些具体实现方法。 3. **数据隐私保护技术**:了解攻击方式后,我们可以研究如何...

    Java memory leaks

    ### Java内存泄漏详解 #### 摘要 本文旨在探讨如何在IBM WebSphere Application Server (WAS) 3.5、4.01 和 5.0 版本上诊断和定位 Java 内存泄漏问题,包括分布式环境和 z/OS 环境。文章将介绍一种通用的方法论,...

    MemoryAnalyzer-1.2.0.20120530-win32.win32.x86_64.zip

    The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption. Use the Memory Analyzer to analyze productive heap dumps with ...

    Springer.The.Developer’s.Guide.to.Debugging.2008.pdf

    4.3.3 Detecting Memory Leaks . . . . . . . 38 4.4 Example 2: Broken Calls to Memory Allocation/Deallocation . . 38 4.5 Combining Memory and Source Code Debuggers . . . . . . 40 4.6 Cutting Down the ...

    MemoryLeaks:内存泄漏的常见情况和使用MLeaksFinder的检测

    平常我们都会用 Instrument 的 Leaks / Allocations 或其他一些开源库进行内存泄露的排查,但是检查过程非常繁琐,而且不清晰,最主要的是Abandoned memory不会被检测出来。 Leaks 从苹果的开发者文档里可以看到,一...

    Finding memory leaks

    在压缩包中的文件,如`memory_leaks.shtml.htm`,可能包含了更详细的内存泄漏检测和解决方法。`VC Empire.htm`可能涉及到在Visual C++环境中如何处理内存泄漏的问题。阅读这些文件可以获取更多实用技巧和案例分析。 ...

    Finding memory leaks发现内存的泄漏(6KB)

    这篇“Finding memory leaks发现内存的泄漏”可能是关于如何定位和解决内存泄漏的技术指南。 在C++编程中,程序员需要手动管理内存,通过`new`关键字申请内存,然后通过`delete`关键字释放内存。如果忘记释放或错误...

    How catch memory leaks with very little effort (7KB)

    标题 "How catch memory leaks with very little effort (7KB)" 提示了这是一个关于如何轻松检测内存泄漏的技术分享。内存泄漏是编程中的一个常见问题,尤其是在C++等不自动管理内存的语言中,程序员需要手动分配和...

    memory leakge & initialization & invalid pointer

    - **Enhancing Security**: Initializing sensitive data to zero or specific values can help prevent information leaks. ##### Best Practices - **Always Initialize Variables**: Make it a habit to ...

    java面试题英文版及其答案

    Once an object is deemed unreachable, the garbage collector reclaims the associated memory, preventing memory leaks. 7. What is a Java package, and why is it used?Answer: A Java package is a ...

    Eliminating Memory Leaks in Symbian OS C++ Projects

    2. **调试信息**:当内存泄漏发生时,Symbian OS会提供详细的调试信息,包括内存泄漏的具体位置等,帮助开发者快速定位问题。 ##### 手动检测 除了系统内置的自动检测机制外,开发者还可以手动设置检查点,确保...

    深入理解计算机系统(英文版)

    1.4 Processors Read and Interpret Instructions Stored in Memory . . . . . . . . . . . . . . . . . 5 1.4.1 HardwareOrganization of aSystem . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.4.2 ...

    Detecting Passive Content Leaks and Pollution in Android Applications

    文章《Detecting Passive Content Leaks and Pollution in Android Applications》主要探讨了在Android应用程序中两个关键的安全漏洞,这些漏洞都与Android的一个不受保护的组件ContentProvider有关。由于缺少必要的...

    checkmemoryleak

    2. **启用包装**:在程序启动时,使用`malloc_hook`函数启用这些包装函数,将它们设置为内存分配函数的替代版本。 3. **跟踪和分析**:当程序运行并调用`malloc()`时,实际上会调用我们的`__wrap_malloc()`。在这个...

    Objective C Memory Management Essentials(PACKT,2015)

    You will begin with a basic understanding of memory management, and why memory leaks occur in an application, moving on to autorelease pools and object creation/storage to get an idea of how memory ...

    Java内存泄漏排除工具mat

    为了有效地排查和解决这类问题,开发者通常会借助专业工具,而“Java内存泄漏排除工具MAT”(Memory Analyzer Tool)就是一个强大的诊断工具。MAT是由Eclipse基金会开发的,用于分析Hprof格式的堆转储文件,帮助...

Global site tag (gtag.js) - Google Analytics