Several methods of memory allocation in Java _java

Source: Internet
Author: User

The upper limit of array allocation

The size of an array in Java is restricted because it uses an int type as an array subscript. This means that you cannot request an array that is larger than the Integer.max_value (2^31-1) size. This is not to say that the upper limit of your application for memory is 2G. You can apply a larger array of types. Like what:

Copy Code code as follows:

Final long[] ar = new long[integer.max_value];

This will allocate 16g-8 bytes, if you set the-XMX parameter is large enough (usually your heap must retain more than 50% space, that is, allocate 16G of memory, you have to set to-xmx24g. This is just the general rules, the specific distribution of more to see the actual situation).

Unfortunately, in Java, because of the type of array elements, you are more cumbersome to manipulate memory. Bytebuffer should be one of the most useful classes in manipulating arrays, and it provides a way to read and write to different Java types. The disadvantage is that the target array type must be byte[], meaning that the maximum memory cache you allocate is 2G.

Second, all arrays are manipulated as byte arrays.

Assuming that 2G memory is not enough for us now, if it is 16G it is OK. We've assigned a long[], but we want to manipulate it as a byte array. In Java we have to help the C Programmer's Good helper--sun.misc.unsafe. This class has two sets of methods: Getn (object, offset), which takes a value of a specified type from the object offset to offset and returns it, where n represents the type to return the value, and putn (Object,offset, Value) method is to write a value to the offset of the object that position.

Unfortunately, these methods can only get or set a value of a type. If you copy data from an array, you need another method of unsafe, CopyMemory (Srcobject, Srcoffset, Destobject,destoffet,count). This is similar to the way system.arraycopy works, but it copies bytes rather than array elements.

To access an array of data through Sun.misc.Unsafe, you need two things:

1. The offset of the data in the array object
2. The offset of the copied elements in the array data
arrays, like any other object in Java, has an object header, which is stored in front of the actual data. The length of the head can be obtained by means of the Unsafe.arraybaseoffset (T[].class) method, where T is the type of an array element. The size of an array element can be obtained by the Unsafe.arrayindexscale (T[].class) method. This means that to access the nth element of type T, your offset should be arrayoffset+n*arrayscale.

Let's write a simple example. We assign a long array, and then we update a few bytes inside it. We update the last element to 1 (16 FFFF FFFF FFFF), and then clear all the bytes of the element one by one.

Copy Code code as follows:

Final long[] ar = new long[1000];
Final int index = AR.LENGTH-1;
ar[index] =-1; FFFF FFFF FFFF FFFF

System.out.println ("Before change =" + long.tohexstring (ar[index));

for (long i = 0; i < 8; ++i)
{
Unsafe.putbyte (AR, longarrayoffset + 8L * index + i, (byte) 0);
System.out.println ("After change:i =" + i + ", val =" + long.tohexstring (ar[index)));
}


To run the example above, add the following static code block to your test class:
Copy Code code as follows:

private static final Unsafe Unsafe;
Static
{
Try
{
Field field = Unsafe.class.getDeclaredField ("Theunsafe");
Field.setaccessible (TRUE);
unsafe = (unsafe) field.get (null);
}
catch (Exception e)
{
throw new RuntimeException (e);
}
}

Private static final Long Longarrayoffset = Unsafe.arraybaseoffset (Long[].class);
The result of the output is:

Copy Code code as follows:

Before change = Ffffffffffffffff
After change:i = 0, val = ffffffffffffff00
After change:i = 1, val = ffffffffffff0000
After change:i = 2, val = ffffffffff000000
After change:i = 3, val = ffffffff00000000
After change:i = 4, val = ffffff0000000000
After change:i = 5, val = ffff000000000000
After change:i = 6, val = ff00000000000000
After change:i = 7, val = 0

Three, Sun.misc.Unsafe memory allocation

As mentioned above, the amount of memory we can allocate in pure Java is limited. This restriction has been set in the initial version of Java, when people were afraid to resemble the memory of allocating several g. But now it's time for big data and we need more memory. In Java, there are two ways to get more memory:


1. Allocate a lot of small chunks of memory, and then logically use them as a continuous large memory.
2. Use Sun.misc.Unsafe.allcateMemory (long) for memory allocation.
The first approach is just a little more interesting from an algorithmic perspective, so let's look at the second method.

Sun.misc.Unsafe provides a set of methods for allocating, reallocating, and releasing memory. They are similar to C's Malloc/free method:

1.long unsafe.allocatememory (long size)--allocates a piece of memory space. This block of memory may contain garbage data (no automatic 0). If the allocation fails, a Java.lang.OutOfMemoryError exception is thrown. It returns a Non-zero memory address (see the description below).
2.unsafe.reallocatememory (long address, long size)--reassign a piece of memory and copy the data from the old memory buffer (where the address points to) into the newly allocated memory block. If the address equals 0, this method is the same as the allocatememory effect. It returns the address of the new memory buffer.
3.unsafe.freememory (long address) frees a memory buffer generated by the previous two methods. If address is 0, nothing is done.

The memory allocated by these methods should be used in a mode called a single register address: unsafe provides a set of methods that accept only one address parameter (unlike the dual-register pattern, which requires an object and an offset). The memory allocated in this way can be larger than what you configure in the-XMX Java parameters.

Note: The memory allocated by unsafe cannot be garbage collected. You have to take it as a normal resource and manage it yourself.

The following is an example of allocating memory using unsafe.allocatememory, and it also checks that the entire memory buffer is not writable:

Copy Code code as follows:

final int size = INTEGER.MAX_VALUE/2;
Final long addr = unsafe.allocatememory (size);
Try
{
System.out.println ("Unsafe address =" + addr);
for (int i = 0; i < size; ++i)
{
Unsafe.putbyte (addr + i, (byte) 123);
if (unsafe.getbyte (addr + i)!= 123)
System.out.println ("Failed at offset =" + i);
}
}
Finally
{
Unsafe.freememory (addr);
}

As you can see, using Sun.misc.Unsafe you could write very generic memory access code: Whatever memory is allocated in Java, you are free to read and write any type of data.

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.