对于我的Java应用程序,我试图使用命令行选项限制堆内存和直接内存使用.
当我试图了解有关Java应用程序内存布局的更多信息时,我遇到了以下VMware 文章.
从文章中,我假设-Xmx设置可用于限制堆使用,而MaxDirectMemory设置可用于限制堆外的本机内存(图中的Guest OS Memory).但是,当我运行一个简单的程序时,结果会有所不同.我使用ByteBuffer.allocateDirect分配本机内存,而ByteBuffer.allocate分配heapmemory.
它是64位处理器(OSX)和64位JVM.
第一次实验
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.util.*;
public class javalimits {
public static void main (String [] args)
throws Exception {
ArrayList al = new ArrayList();
for(int i = 0; i< 100;i++) {
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024* 1024);
al.add(bb);
System.out.println(" Buffer loop "+ i);
Thread.sleep(500);
}
Thread.sleep(10000);
}
}
Run Code Online (Sandbox Code Playgroud)
当我在没有任何选项的情况下运行上述程序时,它在3.6G的内存分配后崩溃了.当我使用"-XX:MaxDirectMemorySize = 100g"选项或 "-Xms100g -Xmx100g"选项时,它在65次循环或大约65G内存分配后崩溃.
我不明白
第二次实验
我将ByteBuffer.allocateDirect更改为ByteBuffer.allocate,以便在堆内存而不是本机内存中进行分配.
import java.nio.ByteBuffer; …Run Code Online (Sandbox Code Playgroud) 像ehcache这样的堆栈缓存有多少数据?
我得到一个24GB的RAM服务器.我可能会开始使用2-4 GB进行缓存,但最终可能会投入20GB左右来缓存.在什么时候我应该担心堆上缓存的GC需要太长时间?
那么,DirectMemory是唯一可用的开源堆外缓存吗?黄金时间准备好了吗?
Java Unsafe类允许您按如下方式为对象分配内存,但是使用此方法如何释放完成时分配的内存,因为它不提供内存地址...
Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
//This creates an instance of player class without any initialization
Player p = (Player) unsafe.allocateInstance(Player.class);
Run Code Online (Sandbox Code Playgroud)
有没有办法从对象引用访问内存地址,也许默认的hashCode实现返回的整数可以工作,所以你可以做...
unsafe.freeMemory(p.hashCode());
Run Code Online (Sandbox Code Playgroud)
似乎没有一些如何......
我在c#中使用serialport组件,效果很好!但问题是如何更快地处理高速(例如2 Mbps)数据传输.
正如我研究过的那样,我发现可以直接访问内存(使用像这个链接的 DMA ).谁能告诉我如何在我的应用程序中定义和使用它?
我要求在GC无法控制的可用RAM中使用空格.我读了几篇同样的文章,介绍了两种方法.它们在以下代码中指定.
package com.directmemory;
Run Code Online (Sandbox Code Playgroud)
import java.lang.reflect.Field; import java.nio.ByteBuffer;
import sun.misc.Unsafe;
公共类DirectMemoryTest {
public static void main(String[] args) {
//Approach 1
ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(8);
directByteBuffer.putDouble(1.0);
directByteBuffer.flip();
System.out.println(directByteBuffer.getDouble());
//Approach 2
Unsafe unsafe = getUnsafe();
long pointer = unsafe.allocateMemory(8);
unsafe.putDouble(pointer, 2.0);
unsafe.putDouble(pointer+8, 3.0);
System.out.println(unsafe.getDouble(pointer));
System.out.println(unsafe.getDouble(pointer+8));
System.out.println(unsafe.getDouble(pointer+16));
}
public static Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
}
我有一些问题
1)为什么我应该注意代码中提到的方法1,因为根据我的理解,ByteBuffer.allocateDirect()不能返回一个存储容量大于2GB的缓冲区?因此,如果我的要求是存储3 GB的数据,我必须创建一个新的缓冲区并将数据存储在那里,这意味着除了存储数据之外,我还有额外的责任来识别相应的缓冲区(在'n列表中) 'buffers),它维护一个指向直接内存的指针.
2)不是方法2比方法1快一点,因为我不必首先找到缓冲区然后找到数据,我只需要一个对象字段的索引机制并使用getDouble/getInt方法并传递绝对值地址 ?
3)与PID相关的直接内存分配(关于堆内存吗?)?如果在一台机器上,我有2个java进程,在PID 1中的allocateMemory调用和PID 2给我永远不会交叉使用的内存块?
4)为什么最后一个sysout语句没有导致0.0?这个想法是每个double使用8个字节,所以我在allocateMemory返回的地址处存储1.0,表示地址= …
directmemory ×5
java ×4
c# ×1
caching ×1
dma ×1
ehcache ×1
heap-memory ×1
jvm ×1
memory ×1
serial-port ×1