程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

jvm010-直接内存

发布于2021-06-14 10:38     阅读(972)     评论(0)     点赞(24)     收藏(0)


目录

1、直接内存概述


1、直接内存概述

①、不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域

②、直接内存是在Java堆外的,直接向系统申请的内存空间

③、来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存

④、通常,访问直接内存的速度会优于Java堆。即读写性能高

  • 因此处于性能考虑,读写频繁的场合可能会考虑使用直接内存
  • Java的NIO库允许Java使用直接内存,用于数据缓冲区

⑤、也可能导致OOM异常

⑥、由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx指定的最大堆大小,但是系统内存时有限的,Java堆和直接内存的总和依然受限于操作系统能给的最大内存

⑦缺点

  • 分配的回收成本较高
  • 不受JVM内存回收管理

⑧、直接内存大小可以通过MaxDirectMemorySize设置

⑨、如果不指定,默认与堆的最大值-Xmx参数值一致

  1. package com.atguigu.java;
  2. import java.nio.ByteBuffer;
  3. import java.util.Scanner;
  4. /**
  5. * IO NIO (New IO / Non-Blocking IO)
  6. * byte[] / char[] Buffer
  7. * Stream Channel
  8. *
  9. * 查看直接内存的占用与释放
  10. * @author
  11. * @create
  12. */
  13. public class BufferTest {
  14. private static final int BUFFER = 1024 * 1024 * 1024;//1GB
  15. public static void main(String[] args){
  16. //直接分配本地内存空间
  17. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
  18. System.out.println("直接内存分配完毕,请求指示!");
  19. Scanner scanner = new Scanner(System.in);
  20. scanner.next();
  21. System.out.println("直接内存开始释放!");
  22. byteBuffer = null;
  23. System.gc();
  24. scanner.next();
  25. }
  26. }

  1. package com.atguigu.java;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.nio.ByteBuffer;
  6. import java.nio.channels.FileChannel;
  7. /**
  8. * @author
  9. * @create
  10. */
  11. public class BufferTest1 {
  12. private static final String TO = "F:\\test\\异界BD中字.mp4";
  13. private static final int _100Mb = 1024 * 1024 * 100;
  14. public static void main(String[] args) {
  15. long sum = 0;
  16. String src = "F:\\test\\异界BD中字.mp4";
  17. for (int i = 0; i < 3; i++) {
  18. String dest = "F:\\test\\异界BD中字_" + i + ".mp4";
  19. // sum += io(src,dest);//54606
  20. sum += directBuffer(src,dest);//50244
  21. }
  22. System.out.println("总花费的时间为:" + sum );
  23. }
  24. private static long directBuffer(String src,String dest) {
  25. long start = System.currentTimeMillis();
  26. FileChannel inChannel = null;
  27. FileChannel outChannel = null;
  28. try {
  29. inChannel = new FileInputStream(src).getChannel();
  30. outChannel = new FileOutputStream(dest).getChannel();
  31. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb);
  32. while (inChannel.read(byteBuffer) != -1) {
  33. byteBuffer.flip();//修改为读数据模式
  34. outChannel.write(byteBuffer);
  35. byteBuffer.clear();//清空
  36. }
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. } finally {
  40. if (inChannel != null) {
  41. try {
  42. inChannel.close();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. if (outChannel != null) {
  48. try {
  49. outChannel.close();
  50. } catch (IOException e) {
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. long end = System.currentTimeMillis();
  56. return end - start;
  57. }
  58. private static long io(String src,String dest) {
  59. long start = System.currentTimeMillis();
  60. FileInputStream fis = null;
  61. FileOutputStream fos = null;
  62. try {
  63. fis = new FileInputStream(src);
  64. fos = new FileOutputStream(dest);
  65. byte[] buffer = new byte[_100Mb];
  66. while (true) {
  67. int len = fis.read(buffer);
  68. if (len == -1) {
  69. break;
  70. }
  71. fos.write(buffer, 0, len);
  72. }
  73. } catch (IOException e) {
  74. e.printStackTrace();
  75. } finally {
  76. if (fis != null) {
  77. try {
  78. fis.close();
  79. } catch (IOException e) {
  80. e.printStackTrace();
  81. }
  82. }
  83. if (fos != null) {
  84. try {
  85. fos.close();
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. }
  89. }
  90. }
  91. long end = System.currentTimeMillis();
  92. return end - start;
  93. }
  94. }

本地内存的OOM 

  1. package com.atguigu.java;
  2. import java.nio.ByteBuffer;
  3. import java.util.ArrayList;
  4. /**
  5. * 本地内存的OOM: OutOfMemoryError: Direct buffer memory
  6. *
  7. * @author
  8. * @create
  9. */
  10. public class BufferTest2 {
  11. private static final int BUFFER = 1024 * 1024 * 20;//20MB
  12. public static void main(String[] args) {
  13. ArrayList<ByteBuffer> list = new ArrayList<ByteBuffer>();
  14. int count = 0;
  15. try {
  16. while(true){
  17. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
  18. list.add(byteBuffer);
  19. count++;
  20. try {
  21. Thread.sleep(100);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. } finally {
  27. System.out.println(count);
  28. }
  29. }
  30. }

设置最大本地内存后的OOM

  1. package com.atguigu.java;
  2. import sun.misc.Unsafe;
  3. import java.lang.reflect.Field;
  4. /**
  5. * -Xmx20m -XX:MaxDirectMemorySize=10m
  6. * @author
  7. * @create
  8. */
  9. public class MaxDirectMemorySizeTest {
  10. private static final long _1MB = 1024 * 1024;
  11. public static void main(String[] args) throws IllegalAccessException {
  12. Field unsafeField = Unsafe.class.getDeclaredFields()[0];
  13. unsafeField.setAccessible(true);
  14. Unsafe unsafe = (Unsafe)unsafeField.get(null);
  15. while(true){
  16. unsafe.allocateMemory(_1MB);
  17. }
  18. }
  19. }

原文链接:https://blog.csdn.net/Choco1ove/article/details/117806236



所属网站分类: 技术文章 > 博客

作者:你不要惹我

链接:http://www.javaheidong.com/blog/article/222683/c81fdbf02f444e17f0c9/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

24 0
收藏该文
已收藏

评论内容:(最多支持255个字符)