Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5334字,纯文字阅读大概需要8分钟。
内容图文
简单总结:
1、内存映射文件
读文件时候一般要两次复制:从磁盘复制到内核空间再复制到用户空间,内存映射文件避免了第二次复制,且内存分配在内核空间,应用程序访问的就是操作系统的内核内存空间,因此极大提高了读取效率。写文件同理。
2、堆内存分配与直接内存分配:
Java申请空间时通常是从JVM堆内存分配的,即 ByteBuffer.allocate(int capacity) ,但其实还可以直接从物理内存(用户空间内存?)分配,即 ByteBuffer.allocateDirect(int capacity) ,后者其实调用了Unsafe类进行分配(见下节)。通常来说,后者的读写性能比前者的好,但是后者的分配比前者慢,特别是在数据量大的情况下差别更明显。
比较:
1 class DirectMemory { 2 3 // 分配堆内存 4 public static void bufferAccess() { 5 long startTime = System.currentTimeMillis(); 6 ByteBuffer b = ByteBuffer.allocate(500); 7for (int i = 0; i < 1000000; i++) { 8for (int j = 0; j < 99; j++) 9 b.putInt(j); 10 b.flip(); 11for (int j = 0; j < 99; j++) 12 b.getInt(); 13 b.clear(); 14 } 15long endTime = System.currentTimeMillis(); 16 System.out.println("access_nondirect:" + (endTime - startTime)); 17 } 1819// 直接分配内存20publicstaticvoid directAccess() { 21long startTime = System.currentTimeMillis(); 22 ByteBuffer b = ByteBuffer.allocateDirect(500); 23for (int i = 0; i < 1000000; i++) { 24for (int j = 0; j < 99; j++) 25 b.putInt(j); 26 b.flip(); 27for (int j = 0; j < 99; j++) 28 b.getInt(); 29 b.clear(); 30 } 31long endTime = System.currentTimeMillis(); 32 System.out.println("access_direct:" + (endTime - startTime)); 33 } 3435publicstaticvoid bufferAllocate() { 36long startTime = System.currentTimeMillis(); 37for (int i = 0; i < 1000000; i++) { 38 ByteBuffer.allocate(1000); 39 } 40long endTime = System.currentTimeMillis(); 41 System.out.println("allocate_nondirect:" + (endTime - startTime)); 42 } 4344publicstaticvoid directAllocate() { 45long startTime = System.currentTimeMillis(); 46for (int i = 0; i < 1000000; i++) { 47 ByteBuffer.allocateDirect(1000); 48 } 49long endTime = System.currentTimeMillis(); 50 System.out.println("allocate_direct:" + (endTime - startTime)); 51 } 5253publicstaticvoid main(String args[]) { 54 System.out.println("访问性能测试:"); 55 bufferAccess(); 56 directAccess(); 5758 System.out.println(); 5960 System.out.println("分配性能测试:"); 61 bufferAllocate(); 62 directAllocate(); 63 } 64} 6566//结果6768访问性能测试: 69 access_nondirect:160 70 access_direct:135 7172分配性能测试: 73 allocate_nondirect:231 74 allocate_direct:644
3、Unsafe类
直接内存分配(allocateDirect)其实就是调用了sun.misc.Unsafe类来进行内存分配,Unsafe是sun.*API中的类,它不是J2SE中真正的一部份。
关于JVM对内存分配、直接内存分配、内存映射文件的一个测试示例:
(2684862条记录,每条记录包含4个long值,所有记录以二进制形式存储在文件中)
以上述三种方式读取每条记录(每种方式都是一次就分配足够的内存):
1 package buaa.act.ucar.imtg.main; 2 3 import java.io.IOException; 4 import java.io.RandomAccessFile; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.FileChannel; 7 import java.nio.channels.FileChannel.MapMode; 8 9 /** 10 * @author zsm 11 * @date 2017年3月3日 上午10:23:53 12 */ 13 public class Test { 14 public static void main(String[] args) 15 throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { 16 long startTime, dataCount; 17 18 try { 19 startTime = System.currentTimeMillis(); 20 System.out.println("reading"); 21 dataCount = readFromMMFile("F:/gps data/2016-11-11 18087 60399647/beijing_0900-1500_2684862.binary"); 22 System.out.printf("reading %d data,time used:%d ms \n", dataCount, 23 (System.currentTimeMillis() - startTime)); 24 } catch (IOException e) { 25// TODO Auto-generated catch block26 e.printStackTrace(); 27 } 2829 } 3031publicstaticlong readFromFile(String srcFilePath) throws IOException { 3233 RandomAccessFile randomAccessFileOutput = new RandomAccessFile(srcFilePath, "rw"); 34 FileChannel inChannel = randomAccessFileOutput.getChannel(); 3536long devsn, gpstime; 37double longitude, latitude; 38long dataCount = 0; 3940 ByteBuffer byteBuffer = ByteBuffer.allocateDirect((int) randomAccessFileOutput.length());// 45ms 41// ByteBuffer byteBuffer = ByteBuffer.allocate((int) randomAccessFileOutput.length());// 46ms 42// while (inChannel.read(byteBuffer) > 0) {// 加上wihle后,分别用时77ms,120ms43 byteBuffer.rewind();// 进入read模式44while (byteBuffer.hasRemaining()) { 45 devsn = byteBuffer.getLong(); 46 gpstime = byteBuffer.getLong(); 47 longitude = Double.longBitsToDouble(byteBuffer.getLong()); 48 latitude = Double.longBitsToDouble(byteBuffer.getLong()); 49// System.out.println(devsn + " " + gpstime + " " + longitude + " " + latitude);50 dataCount++; 51 } 52 byteBuffer.clear();// 进入write模式 53// }54 inChannel.close(); 55 randomAccessFileOutput.close(); 56return dataCount; 57 } 5859// 22ms60publicstaticlong readFromMMFile(String srcFilePath) throws IOException { 61 RandomAccessFile randomAccessFileOutput = new RandomAccessFile(srcFilePath, "rw"); 62 FileChannel inChannel = randomAccessFileOutput.getChannel(); 6364long devsn, gpstime; 65double longitude, latitude; 66long dataCount = 0; 67 ByteBuffer byteBuffer = inChannel.map(MapMode.READ_ONLY, 0, randomAccessFileOutput.length()); 68while (byteBuffer.hasRemaining()) { 69 devsn = byteBuffer.getLong(); 70 gpstime = byteBuffer.getLong(); 71 longitude = Double.longBitsToDouble(byteBuffer.getLong()); 72 latitude = Double.longBitsToDouble(byteBuffer.getLong()); 73// System.out.println(devsn + " " + gpstime + " " + longitude + " " + latitude);74 dataCount++; 75 } 76 inChannel.close(); 77 randomAccessFileOutput.close(); 78return dataCount; 79 } 8081 }
前两者要45ms左右,而内存映射文件只要22ms左右。
原文:http://www.cnblogs.com/z-sm/p/6725698.html
内容总结
以上是互联网集市为您收集整理的Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)全部内容,希望文章能够帮你解决Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。