Android development: this is an interesting phenomenon caused by dv Virtual Machine resource recovery. It is attached with an available zip tool class.

Source: Internet
Author: User

Since I started to use Android and Java, I have had many "amazing" contact with jvm and its gc mechanism. Many jvm gc implementations have different strategies. I personally know that, even the implementations of various Android mobile phone manufacturers (of course, strictly speaking, Android is not a JVM) are even different. What you encounter is really tearful. For example, when softreference or weakreference is involved, do not be surprised when you find that the program behavior is inconsistent with the instructions in the document.

 

The android documentation is not perfect in many places, such as bitmap. The document clearly states that recycle is generally not required, but the comrades who have used it should understand that do you dare not recycle? (I am not really sure ...) Of course, the topic is too long to complain. No, I encountered another problem two days ago. I encountered this problem once before, and I was confused and confused. Once again, after careful observation, careful consideration, experimentation, data investigation, and tangle, we finally found the essentials and verified them.

 

Assume that there is a class named publicarea and another class named ziputil. The former is mainly used for data exchange and contains some global data. The latter provides a zip-related static method, extract the file data of the specified file name from the byte [] or inputstrem object.

The publicarea class defines two global variables as follows:

 

public static byte[] mZipdata=null; 
public static InputStream mZipIS=null;

 

The ziputil class is defined as follows:

public class ZipUtil{

public static Map<String,byte[]> unzipFilesFromStream(InputStream is,String type) throws Exception
{
Map<String, byte[]> result = new HashMap<String, byte[]>();
ZipInputStream zipStream=new ZipInputStream(is);
ZipEntry zipEntry;
while((zipEntry=zipStream.getNextEntry())!=null){
if (zipEntry.getName().endsWith("."+type))
{
int zipsize=(int)zipEntry.getSize();
byte[] temp=new byte[zipsize];
byte[] beRead=new byte[zipsize];
int nowpos=0;
int beReadThisTime=0;
while(-1!=(beReadThisTime=zipStream.read(temp)))
{
System.arraycopy(temp,0,beRead,nowpos,beReadThisTime);
nowpos+=beReadThisTime;
temp=new byte[zipsize];
}
result.put(zipEntry.getName(), beRead);
}
zipStream.closeEntry();
}
zipStream.close();
return result;
}


public static byte[] unzipFileFromStream(InputStream is,String filename) throws Exception
{
byte[] result =null;
ZipInputStream zipStream=new ZipInputStream(is);
ZipEntry zipEntry;
while((zipEntry=zipStream.getNextEntry())!=null){
if (zipEntry.getName().equals(filename))
{
int zipsize=(int)zipEntry.getSize();
byte[] temp=new byte[zipsize];
byte[] beRead=new byte[zipsize];
int nowpos=0;
int beReadThisTime=0;
while(-1!=(beReadThisTime=zipStream.read(temp)))
{
System.arraycopy(temp,0,beRead,nowpos,beReadThisTime);
nowpos+=beReadThisTime;
temp=new byte[zipsize];
}
result=beRead;
}
zipStream.closeEntry();
}
zipStream.close();
return result;
}

}

 

In publicarea, I obtain the binary data of a zip file through a series of actions (for example, reading a file or transmitting it from the Network), reference the object to mzipdata, and then use the following code:

mZipIS = new ByteArrayInputStream(mZipdata);

Create a byte stream and assign the reference value to mzipis.

At this point, mzipdata and mzipis have created corresponding objects, and because both are global variables, these two objects will survive unless I manually give up the reference.

The two methods in ziputil are:

public static byte[] unzipFileFromStream(InputStream is,String filename) 

public static Map<String,byte[]> unzipFilesFromStream(InputStream is,String type)

The former obtains the binary object of the file named filename in the zip package based on the given inputstream.

The latter is to traverse the files in the zip package and store the binary Byte object of the file with the suffix type into a hashmap. The key is the file name.

Here, Zip is used for fast traversal, and its structure is suitable for extracting file names.

 

The problem is that I need to use the two methods in ziputil first, unzipfilefromstream, and then unzipfilesfromstream. The inputstream parameter is of course the mzipis in publicarea. However, when the ziputil method is called for the second time, "nullpointerexception" will pop up, which is really painful. The mzipis object is created when unzipfilefromstream is called for the first time, and the method is run out. Other threads will call the unzipfilesfromstream method later, and the mzipis parameter is still taken for granted, then the exception is shameful. Ziputil is recycled. In fact, at the beginning, I did not call zipstream in ziputil implementation. close (); in this case, there should be no such problem on the surface. How did this problem come about? This will start from multiple aspects.

 

First, let's review a small feature of Java's Io class. Java's Io class implementation is classic. All stream class implementations are classified into node streams and filter streams, A "decorative design model" is used to build a chain structure. Let's talk about the release of its resources. When you concatenate various filter streams and close them, you only need to filter the last stream (that is, the tail end of the string) you can call the close () method to release the stream objects in the entire chain structure.

 

 

The problem I encountered was that in ziputil's method implementation, a zipinputstream was added to the mzipis end to filter the stream, and it was a local variable, so... After the method is executed, the chain structure is released and mzipis is exhausted. Although the reference of mzipis still exists, the GC of the DV virtual machine still recycles it. On the one hand, the GC policy of the DV virtual machine is as much as possible, and on the other hand, we must realize that, GC intelligence is limited after all. At the same time, good coding habits of programmers are very important. There must be no perfect JVM and GC. Do not add the automatic recycling mechanism to too complex program processes, otherwise, it would be a tough task. For simple program flows, the GC behavior of most JVM should be basically the same, because there is no good choice, so it is relatively safe. Although we can blame JVM for many problems and their GC is not perfect,... What can you do with the machine --#

 

 

Here we can also see that for the reference of global data storage such as mzipdata, where the stream is generated and where it ends, do not rely on a stream object fantasy to use eight hundred times, A series of demand-oriented chain structures that you have combined are destroyed when they are used up. This makes it a good habit to manually destroy them. You should naturally know how to create them when they are used. For data reference persistence, use byte [] for reference. When using it, create a stream. This is clear and easy to understand. You cannot be too lazy. Of course, let's do it in extreme cases. For example, the Shenma network is not smooth and there is no storage space and there is not enough memory .... Then let the program commit suicide (joking) and run the question. Haha.

 

By the way, the zip tool class can be used directly. If you have any questions, please discuss them.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.