DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Analyzing “java.lang.OutOfMemoryError: Failed to create a thread” Error
  • Fixing OutOfMemoryErrors in Java Applications
  • Understanding Root Causes of Out of Memory (OOM) Issues in Java Containers
  • Singleton: 6 Ways To Write and Use in Java Programming

Trending

  • Docker Model Runner: Streamlining AI Deployment for Developers
  • Recurrent Workflows With Cloud Native Dapr Jobs
  • Hybrid Cloud vs Multi-Cloud: Choosing the Right Strategy for AI Scalability and Security
  • My LLM Journey as a Software Engineer Exploring a New Domain
  1. DZone
  2. Coding
  3. Java
  4. Native Memory May Cause Unknown Memory Leaks

Native Memory May Cause Unknown Memory Leaks

Recently I came across a strange case: the memory usage of my program exceeded the maximum value intended for the heap. I found an interesting issue.

By 
Reza Ganji user avatar
Reza Ganji
DZone Core CORE ·
Jan. 31, 21 · Tutorial
Likes (11)
Comment
Save
Tweet
Share
6.6K Views

Join the DZone community and get the full member experience.

Join For Free

Recently I came across a strange case: the memory usage of my program exceeded the maximum value intended for the heap. Even after running GC, part of the memory was not free. I already knew that a part of  JVM memory would be allocated to native memory and part of native memory allocated to C code, but I did not have even one line of native code in my program. After reviewing and profiling my code several times, I found an interesting issue. Before diving into the problem, let's look at Java memory concepts.

Memory Management in Java

 JVM divides memory into two major spaces, heap and native memory. Heap spaces are used for allocating Java objects whereas native memory is the memory available to the OS. There is a key difference between Java 7 and 8 in the memory management model. Java 7 has PermGen; PermGen is the memory area in the heap that is used by the JVM to store class metadata, static content, primitive variables. Java 8 has eliminated PermGen and added Metaspace; actually, Metaspace and PermGen do the same thing. The main difference is that PermGen is part of the Java heap while Metaspace is NOT part of the heap. Rather Metaspace is part of native memory, which is only limited by the Host Operating System.

Java 7 JVM vs. Java 8 JVM

Native Memory

Native memory is a memory area outside the normal JVM heap but generally is a part of total memory spared by OS for the JVM process. Part of native memory is assigned to the C heap; the C heap is space that used by native C programs in Java programs.

Native Memory Tracking (NMT)

NMT is a memory tracking tool used to monitor the native memory usage of the program. You can access NMT data using jcmd utility. NMT is not enabled by default; you can enable it by adding the following parameters to JVM options:

-XX:NativeMemoryTracking=detail-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

For monitoring and tracking memory changes during execution you should use the following command: 

jcmd <pid> VM.native_memory detail.diff

<pid> is the exact process id of your Java program in Linux. In my case my <pid> is '92165' so I executed this command:

jcmd 92165 VM.native_memory detail.diff.

Consider that  monitoring is a time-based approach it means that you should compare memory state in time T2 with the state in time T1, so  you need to mark the state of T1 as a baseline by using the following command:

jcmd 92165 VM.native_memory baseline

I also executed these commands in chronological order:

DEC 19, 2020 9:07:10 AM IRS :jcmd 92165 VM.native_memory baseline

DEC 19, 2020 12:07:10 PM IRS:jcmd 92165 VM.native_memory detail.diff. 

The output of that was something like this:

 reserved 3892 KB for Thread Stack        
        from [Thread::record_stack_base_and_size()+0xca]      

[0x9f586000 - 0x9f791000] reserved 1680KB for Thread Stack        
        from [Thread::record_stack_base_and_size()+0xca]     

I tried to execute the command jcmd 92165 VM.native_memory detail.diff at different times, and I was getting different results every moment, which means that my native memory usage is growing over time.

So, What's the Problem?!

In the previous part, I said my native memory grows over time, and I was sure I have no native code in my program, but then what is the problem? I started tracing the program at the same time as monitoring, and I found an interesting thing: there was a usage of java.util.zip code in the program. Once I reached this code the usage of native memory increased significantly. The problem was clear; this package classes internally and uses native codes. If you take a look at JDK source at jdk8 source, you can find interesting codes like this, implementations of certain classes based on native codes and C:

Java
 




xxxxxxxxxx
1
72


 
1
src/share/native/java/util/zip/ZipFile.c 
2
JNIEXPORT jlong JNICALL
3
Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name,
4
                                        jint mode, jlong lastModified,
5
                                        jboolean usemmap)
6
{
7
    const char *path = JNU_GetStringPlatformChars(env, name, 0);
8
    char *msg = 0;
9
    jlong result = 0;
10
    int flag = 0;
11
    jzfile *zip = 0;
12

          
13
    if (mode & OPEN_READ) flag |= O_RDONLY;
14
    if (mode & OPEN_DELETE) flag |= JVM_O_DELETE;
15

          
16
    if (path != 0) {
17
        zip = ZIP_Get_From_Cache(path, &msg, lastModified);
18
        if (zip == 0 && msg == 0) {
19
            ZFILE zfd = 0;
20
#ifdef WIN32
21
            zfd = winFileHandleOpen(env, name, flag);
22
            if (zfd == -1) {
23
                /* Exception already pending. */
24
                goto finally;
25
            }
26
#else
27
            zfd = JVM_Open(path, flag, 0);
28
            if (zfd < 0) {
29
                throwFileNotFoundException(env, name);
30
                goto finally;
31
            }
32
#endif
33
            zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap);
34
        }
35

          
36
        if (zip != 0) {
37
            result = ptr_to_jlong(zip);
38
        } else if (msg != 0) {
39
            ThrowZipException(env, msg);
40
            free(msg);
41
        } else if (errno == ENOMEM) {
42
            JNU_ThrowOutOfMemoryError(env, 0);
43
        } else {
44
            ThrowZipException(env, "error in opening zip file");
45
        }
46
finally:
47
        JNU_ReleaseStringPlatformChars(env, name, path);
48
    }
49
    return result;
50
}
51

          
52
JNIEXPORT jint JNICALL
53
Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile)
54
{
55
    jzfile *zip = jlong_to_ptr(zfile);
56

          
57
    return zip->total;
58
}
59

          
60
JNIEXPORT jboolean JNICALL
61
Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
62
{
63
    jzfile *zip = jlong_to_ptr(zfile);
64

          
65
    return zip->locsig;
66
}
67

          
68
JNIEXPORT void JNICALL
69
Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
70
{
71
    ZIP_Close(jlong_to_ptr(zfile));
72
}


Remember that native codes are not just in these classes. There are a lot of components, like components that interact with devices or communication components, that potentially use native codes.



Memory (storage engine) Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Analyzing “java.lang.OutOfMemoryError: Failed to create a thread” Error
  • Fixing OutOfMemoryErrors in Java Applications
  • Understanding Root Causes of Out of Memory (OOM) Issues in Java Containers
  • Singleton: 6 Ways To Write and Use in Java Programming

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!