Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to deal with memory loopholes in Java programs

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article shows you how to deal with memory loopholes in Java programs, which is concise and easy to understand, which will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.

Are there memory vulnerabilities in Java programs? Of course there is. Contrary to popular belief, memory management is still a consideration in Java programming. In this article, you will learn what causes memory vulnerabilities and when to focus on them. You also have the opportunity to practice solving vulnerabilities in your own projects.

How to show the memory loophole in Java program

Most programmers know that one of the benefits of using a programming language like Java is that they no longer have to worry about memory allocation and release. All you have to do is create objects, and when the application no longer needs them, Java deletes them through a mechanism called garbage collection. This processing means that Java has solved the annoying problem that beset other programming languages-terrible memory vulnerabilities. Is that really the case?

Before going any further, let's review how garbage collection works. The job of the garbage collector is to find objects that the application no longer needs and delete them when they are no longer accessed or referenced. The garbage collector traverses all referenced nodes for cleanup, starting with the root nodes (those classes that always exist throughout the life cycle of the Java application). As it traverses these nodes, it keeps track of which objects are currently being referenced. Any class is eligible for garbage collection as long as it is no longer referenced. When these objects are deleted, the memory resources they occupy can be returned to the Java virtual machine (JVM).

So it is true that Java code does not require programmers to manage and clear memory, it automatically performs garbage collection on useless objects. However, one thing to keep in mind is that an object is counted as useless only when it is no longer referenced. Figure 1 illustrates this concept.

Figure 1. Objects that are useless but still referenced

The above illustrates two classes that have different life cycles during the execution of the Java application. Class An is first instantiated and exists for a long time or the entire lifetime of the program. At some point, class B is created and class An adds a reference to the newly created class. Now, let's assume that class B is a user interface widget that is displayed or even released by the user. If the reference of class A to B is not cleared, class B will still exist and take up memory space even after the next garbage collection cycle, even if class B is no longer needed.

When should attention be paid to memory vulnerabilities

If your program issues a java.lang.OutOfMemoryError error after a period of execution, memory vulnerabilities must be a major suspect. Apart from this obvious situation, when should we pay attention to memory vulnerabilities? Programmers with a perfectionist view will certainly answer that all memory vulnerabilities should be found and corrected. However, before reaching this conclusion, there are several aspects to consider, including the lifetime of the program and the size of the vulnerability.

It is entirely possible that the garbage collector may never run during the lifetime of the application. There is no guarantee when and whether JVM will call the garbage collector-- even if the program explicitly calls System.gc (). In general, JVM does not run the garbage collector automatically when the current available memory meets the memory requirements of the program. When the available memory does not meet the requirements, JVM will first try to free more available memory by invoking garbage collection. If this attempt still does not release enough resources, JVM will get more memory from the operating system until the maximum allowed limit is reached.

For example, consider a small Java application that displays some simple user interface elements for modifying the configuration, and it has a memory vulnerability. It is likely that the garbage collector will not be called when the application closes, because JVM probably has enough memory to create all the objects the program needs, and then there is little available memory. Therefore, in this case, even if some "dead" object takes up memory while the program is executing, it is actually of no use.

If the Java code you are developing is going to run on the server 24 hours a day, the impact of memory vulnerabilities is much greater here than in our configuration utility. In some code that takes a long time to run, even the smallest vulnerability can cause JVM to use up all available memory.

On the contrary, even if the program has a short lifetime, it is still possible to reach the memory limit if there is any Java code that allocates a large number of temporary objects (or several objects that consume a lot of memory) and does not dereference them when they are no longer needed.

The last case is that memory vulnerabilities don't matter. We should not assume that Java memory vulnerabilities are as dangerous as vulnerabilities in other languages, such as C++, where memory is lost and never returned to the operating system. In Java applications, we attach unwanted objects to the memory resources provided by the operating system for JVM. So in theory, once the Java application and its JVM are closed, all allocated memory will be returned to the operating system.

Determine if the application has a memory leak

To see if a Java application running on the Windows NT platform has memory vulnerabilities, you may try to observe the memory settings in the Task Manager while the application is running. However, after looking at several Java applications that are running, you will find that they take up much more memory than local applications. Some of the Java projects I've done require 10 to 20 MB of system memory to start. The Windows Explorer program that comes with the operating system only needs about 5 MB of memory.

Another thing to note about the memory usage of Java applications is that this typical program is taking up more and more system memory when running in IBM JDK 1.1.8 JVM. It doesn't seem to return memory to the system until a very large amount of physical memory has been allocated to it. Are these conditions a sign of memory vulnerabilities?

To understand why, we must be familiar with how JVM uses system memory as its heap. When running java.exe, you use options to control the starting and maximum size of the garbage collection heap (represented by-ms and-mx, respectively). The default starting setting for Sun JDK 1.1.8 is 1 MB, and the default maximum setting is 16 MB. The default maximum setting for IBM JDK 1.1.8 is half the total physical memory size of the system. These memory settings have a direct impact on what JVM does when it runs out of memory. JVM may continue to grow the heap without waiting for a garbage collection cycle to complete.

In this way, in order to find and eventually eliminate memory vulnerabilities, we need to use a better tool than the task monitoring utility. The memory debugger (see Resources) may come in handy when you try to debug memory vulnerabilities. These programs typically display information such as the number of objects in the heap, the number of instances of each object, and the memory consumed by these objects. In addition, they may provide useful views that show references and references to each object so that you can track the source of memory vulnerabilities.

Below I'll show you how I used Sitraka Software's JProbedebugger to detect and remove memory vulnerabilities to give you an idea of how these tools are deployed and the process required to successfully remove them.

An example of memory loophole

This example focuses on one problem. Our department was developing a commercial distribution software, an Java JDK 1.1.8 application, and it took a tester several hours to study it before the problem finally became apparent. The basic code and packages for this Java application are developed by several different development teams at different times. I suspect that unexpected memory vulnerabilities in this application are caused by programmers who don't really understand the code developed by others.

The Java code we're talking about allows users to create applications for Palm personal digital assistants without having to write any Palm OS native code. By using the graphical user interface, users can create forms, add controls to the form, and then connect the events of those controls to create Palm applications. Testers found that the Java application eventually ran out of memory as forms and controls were created and deleted. Developers did not detect this problem because their machines had more physical memory.

To study this problem, I use JProbe to determine what went wrong. Despite the powerful tools and memory snapshots provided by JProbe, research is still a tedious and repetitive process, first determining the cause of memory vulnerabilities, then modifying the code, and finally testing the results.

JProbe provides several options to control what information is actually recorded during debugging. After several experiments, I decided that the most effective way to get the information I needed was to turn off performance data collection and focus on the captured heap data. JProbe provides a view called Runtime Heap Summary, which shows the amount of heap memory consumed by Java applications over time. It also provides a toolbar button to force JVM to perform garbage collection if necessary. This is useful if you are trying to figure out whether a given class instance will be used as garbage collection when a Java application no longer needs it. Figure 2 shows the variation of heap storage in use over time.

Figure 2. Runtime Heap Summary

In Heap Usage Chart, the blue part indicates the amount of heap space allocated. After starting the Java program and reaching a steady state, I force the garbage collector to run, which is shown in the figure as a sharp drop in the blue line to the left of the green line (which indicates that a checkpoint has been inserted). Then I added four forms, then deleted them, and called the garbage collector again. When the program returns to the initial state with only one visual form, the blue area after the checkpoint is higher than the blue area before the checkpoint, indicating a possible memory vulnerability. I confirmed that there was a vulnerability by looking at Instance Summary, because Instance Summary indicated that the count of the FormFrame class (which is the main user interface class for the form) increased by 4 after the checkpoint.

Find the reason

In order to weed out the problems reported by the tester, the first step I took was to find a few simple and repeatable test cases. In this case, I found that simply adding a form, deleting it, and then forcing garbage collection would result in many class instances associated with the deleted form still active. This problem is evident in JProbe's Instance Summary view, which counts the number of instances of each Java class in the heap.

To find out the references that prevent the garbage collector from doing its job properly, I use JProbe's Reference Graph (shown in figure 3) to determine which classes still reference the currently undeleted FormFrame class. This process is one of the most complex when debugging this problem, because I find that many different objects still refer to this useless object. The trial and error process used to find out which user is really causing the problem is time-consuming.

In this case, a root class (the one in red in the upper left corner) is the source of the problem. The class highlighted in blue on the right is on the path tracked from the original FormFrame class.

Figure 3. Track memory vulnerabilities in the reference graph

In this case, it turns out that the culprit is the font manager class that contains a static hashtable. By retroactively tracing the list of references, I found that the root node is a static hashtable used to store the fonts used by each form. Individual forms can be zoomed in or out individually, so this hashtable contains a vector with all the fonts for a given form. When the size of the form changes, the font vector is extracted and the appropriate scaling factor is applied to the font size.

The problem with this font manager class is that although the program stores the font vector in the hashtable when the form is created, it does not provide the code to delete the vector when the form is deleted. Therefore, this static hashtable (which exists for the lifetime of the application) never removes the keys that reference each form. As a result, the form and all its associated classes are idle in memory.

Correction

A simple solution to this problem is to add a method to the font manager class to call the remove () method of hashtable with the appropriate key as a parameter when the user deletes the form. The removeKeyFromHashtables () method is as follows:

Public void removeKeyFromHashtables (GraphCanvas graph) {

If (graph! = null) {

ViewFontTable.remove (graph); / / Delete keys in hashtable

/ / to prevent memory leaks

}

}

I then added a call to this method to the FormFrame class. FormFrame actually uses Swing's internal framework to implement the form's user interface, so I add the call to the font manager to the method that is called when the internal frame is completely closed, as follows:

/ * *

* called when (dispose) FormFrame is removed. Clear references to prevent memory leaks.

* /

Public void internalFrameClosed (InternalFrameEvent e) {

FontManager.get () removeKeyFromHashtables (canvas)

Canvas = null

SetDesktopIcon (null)

}

After taking these changes, I use the debugger to verify that when the same test case is executed, the number of objects associated with the deleted form decreases.

Prevent memory leaks

Memory leaks can be prevented by observing some common problems. Collection classes, such as hashtable and vector, are often places where memory vulnerabilities occur. This is especially true when this class is declared with the static keyword and exists throughout the lifetime of the application.

Another common problem is that you register a class as an event listener without unregistering the class when it is no longer needed. In addition, you often need to set the class member variable that points to other classes to null when appropriate.

Summary

Finding the cause of memory vulnerabilities can be a tedious process, not to mention the need for dedicated debugging tools. However, once you are familiar with these tools and the pattern of searching when tracking object references, you can find memory vulnerabilities. In addition, you will explore some valuable techniques that will not only help save the cost of the project, but also enable you to understand which coding methods should be avoided in future projects to prevent memory vulnerabilities.

The above content is how to deal with memory vulnerabilities in Java programs. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report