在Hotspot JVM上,我们能够直接对内存进行读写操作。该类的allocateMemory方法用于申请分配内存,putAddress和getAddress方法用于对直接内存进行读写。
下面将通过sun.misc.Unsafe演示直接读写内存的例子。
注意:这只是一个例子,只是用来验证通过sun.misc.Unsafe来实现直接读写内存的可能性。但是,这样做并没有安全保证,而且稍微有点疏忽将可能导致JVM崩溃。
Unsafe类的三个方法:allocateMemory,putAddress和getAddress如下:
1. long allocateMemory(long bytes)
申请分配内存
2. long getAddress(long address) 和void putAddress(long address, long x)
对直接内存进行读写
3.putByte、getByte方法,这两个方法deprecated了
因为Unsafe这个类的访问是受限的,只有rt.jar中的类才能使用Unsafe的功能,它的构造方法是私有的,所以,我们不能通过new来创建实例。但是,可以通过反射的方法来获取Unsafe实例。
实例一:
package my.memory; import java.lang.reflect.Field; import sun.misc.Unsafe; public class DirectMemoryAccess { public static void main(String[] args) { /* * Unsafe的构造函数是私有的,不能通过new来获得实例。 * * 通过反射来获取 */ Unsafe unsafe = null; Field field = null; try { field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); /* * private static final Unsafe theUnsafe = new Unsafe(); * * 因为field的修饰符为 private static final, * 需要将setAccessible设置成true,否则会报java.lang.IllegalAccessException */ field.setAccessible(true); unsafe = (Unsafe) field.get(null); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } long oneHundred = 100; byte size = 1; /* * 调用allocateMemory分配内存 */ long memoryAddress = unsafe.allocateMemory(size); /* * 将100写入到内存中 */ unsafe.putAddress(memoryAddress, oneHundred); /* * 内存中读取数据 */ long readValue = unsafe.getAddress(memoryAddress); System.out.println("Val : " + readValue); } }
输出结果:
Val : 100
实例二:
package my.memory; import java.lang.reflect.Field; import java.util.Arrays; import sun.misc.Unsafe; public class DirectMemoryTest { private static int byteArrayBaseOffset; public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe UNSAFE = (Unsafe) theUnsafe.get(null); System.out.println(UNSAFE); byte[] data = new byte[10]; System.out.println(Arrays.toString(data)); byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class); System.out.println("byteArrayBaseOffset:" + byteArrayBaseOffset); UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1); UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5); System.out.println(Arrays.toString(data)); } }
运行结果:
sun.misc.Unsafe@de6ced [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] byteArrayBaseOffset:12 [1, 0, 0, 0, 0, 5, 0, 0, 0, 0]
实例三:
package my.memory; import java.lang.reflect.Field; import sun.misc.Unsafe; public class SuperArray { private final static int BYTE = 1; private long size; private long address; public SuperArray(long size) { this.size = size; //得到分配内存的起始地址 address = getUnsafe().allocateMemory(size * BYTE); } public void set(long i, byte value) { getUnsafe().putByte(address + i * BYTE, value); } public int get(long idx) { return getUnsafe().getByte(address + idx * BYTE); } public long size() { return size; } private static Unsafe getUnsafe() { Unsafe unsafe = null; Field field = null; try { field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); /* * private static final Unsafe theUnsafe = new Unsafe(); * 因为field的修饰符为 private static final, * 需要将setAccessible设置成true,否则会报java.lang.IllegalAccessException */ field.setAccessible(true); unsafe = (Unsafe) field.get(null); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return unsafe; } public static void main(String[] args) { int sum = 0; long SUPER_SIZE = (long)Integer.MAX_VALUE * 2; SuperArray array = new SuperArray(SUPER_SIZE); System.out.println("Array size:" + array.size()); // 4294967294 for (int i = 1; i <= 100; i++) { array.set((long)i, (byte)3); sum += array.get((long)i); } System.out.println("Sum of 100 elements:" + sum); // 300 } }
运行结果:
Array size:4294967294 Sum of 100 elements:300
参考文章:
http://mouselearnjava.iteye.com/blog/1922390
http://tech.ddvip.com/2014-06/1403069715211221_2.html
PS:Unsafe的源代码,请参考下面的链接
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
相关推荐
Java内存模型是Java虚拟机规范中定义的一部分,它规定了Java程序中变量的读写行为,以及线程之间的交互规则。理解Java内存模型对于编写正确、高效的多线程程序至关重要。在Java 5之前,Java内存模型的描述比较模糊,...
下面将详细阐述DOM模型、解析过程以及如何在Java中使用DOM进行XML读写。 DOM模型的核心概念是节点(Node)。XML文档的每个部分——元素(Element)、属性(Attribute)、文本(Text)等都被表示为一个节点对象。DOM...
遗憾的是,提供的文件列表中只有`jeebbs-db-3.sql`,这似乎是一个SQL数据库文件,与Java POI读写Excel的主题并不直接相关。通常,SQL文件用于导入或导出数据库的数据,如果博客作者有提到结合Java POI与SQL操作Excel...
理解Java内存模型对于编写多线程并发程序至关重要,因为它直接影响到程序的正确性和性能。 在Java中,内存分为以下几个区域: 1. **程序计数器**:每个线程都有自己的程序计数器,用于存储当前线程执行的字节码...
【深入解读 Java 堆外内存(直接内存)】 Java 堆外内存,又称直接内存(Direct Memory),是 Java 程序中除JVM堆内存之外的一种内存区域。它并不遵循JVM规范中定义的标准内存模型,而是直接与操作系统交互,用于...
内存读写是计算机编程中的一个基础且重要的概念,特别是在低级编程、游戏修改、系统调试等领域。`Mem.wri` 类似乎是为简化内存操作而设计的一个工具,它可能包含了一系列用于读取和写入内存的函数或方法。下面将详细...
本篇将深入探讨Java中XML文档的读写方法,包括直接读写、DOM(Document Object Model)树解析以及对象序列化。 1. 直接读写: XML文档的直接读写通常涉及到流式处理,如使用Java的`java.io`包中的`InputStream`和`...
标题"JAVA读写EXCEL下载直接用"暗示我们将讨论如何直接使用Java来读写Excel文件,而无需安装额外的软件。Apache POI项目提供的API简化了这一过程,你可以在项目中直接引入对应的jar包,如压缩包中的"poi-bin-3[1].0-...
线程对变量的所有操作都必须在工作内存中进行,不能直接读写主内存。 3. **读写操作**:JMM规定了8种基本操作,包括读取(read)、加载(load)、使用(use)、赋值(assign)、存储(store)、写入(write)、锁定...
volatile关键字则保证了变量的读写操作直接在主内存中进行,确保了变量的更新对其他线程立即可见。而Java并发包中的AtomicInteger、Semaphore等工具类则提供了更细粒度的控制和更强大的功能。 总的来说,Java内存...
Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一部分,用于规定程序中的各种变量(包括实例字段、静态字段和数组元素等)在多个线程共享内存中的读写行为。JMM的主要目的是确保所有线程能够看到一致...
Java虽然原生并不直接支持共享内存,但可以通过NIO(New IO)库中的MAPPED_BUFFER类,结合底层操作系统提供的文件映射功能来间接实现。文件映射编程是将一个文件或者一部分文件映射到进程的虚拟地址空间,这样就可以...
### Java内存监控工具Java VisualVM #### 一、概述 Java VisualVM是一款强大的Java应用程序性能分析和诊断工具,主要用于监控和分析Java应用的运行时行为,包括但不限于内存使用情况、线程状态、CPU使用率等关键...
- **使用流式API**:如使用Apache POI的SXSSFWorkbook,可直接将数据写入磁盘,减少内存消耗。 5. **错误处理和异常**: - 对可能出现的异常进行捕获,如IOException(文件操作)、SQLException(数据库操作)等...
1. **IO流概念**:Java的IO流是一个数据传输机制,它允许程序与外部资源(如文件、网络连接或内存缓冲区)进行交互。IO流分为字节流和字符流,字节流处理原始的字节数据,而字符流处理字符编码的数据。 2. **File类...
在Java编程语言中,XML(eXtensible Markup Language)是一种重要的数据交换格式,用于存储和...在提供的"在java中读写XML文件.ppt"和"源码"中,可能包含了更多详细的步骤和示例代码,可以帮助你进一步理解这个主题。
### Java删除某行和读写TXT文件 在Java中,如果需要从文本文件中删除特定行,实际上并没有直接提供这样的方法。通常的做法是先将文件中的所有内容读取到内存中,然后根据需要过滤掉不需要的行,最后再将处理后的...
共享内存是一种在多个进程间高效传递数据的方法,它允许进程直接读写同一块物理内存,从而避免了传统IPC(Inter-Process Communication)方式中的数据复制开销。在Java中,可以通过`java.nio.MappedByteBuffer`类来...
本文将深入探讨内存读写操作的基本概念、原理以及相关技术,旨在帮助你理解如何对内存进行有效管理和操作。 一、内存读写基本概念 1. 内存地址:每个内存单元都有一个唯一的地址,CPU通过这个地址来访问和操作内存...