从一个例子看JVM启动过程(2)

其实,在代码执行到Main函数之前,需要加载初始化很多类。在初始化虚拟机的这段时间中,Bits类先于VM类初始化,即在VM还没有初始化完的时候,Bits类就已经开始初始化静态属性maxMemory,而通过反射拿到的值也是这个时候设置的值。具体过程如下:
private static volatile long maxMemory = VM.maxDirectMemory();
public static long maxDirectMemory() {
//这个时候VM还没初始化好,跳过此分支
if (booted)
return directMemory;

Properties p = System.getProperties();
String s = (String)p.remove("sun.nio.MaxDirectMemorySize");
System.setProperties(p);
//因为System也未初始化好,所以s==null。跳过此分支。
if (s != null) {
if (s.equals("-1")) {
// -XX:MaxDirectMemorySize not given, take default
directMemory = Runtime.getRuntime().maxMemory();
} else {
long l = Long.parseLong(s);
if (l > -1)
directMemory = l;
}
}
//直接返回directMemory属性
return directMemory;
}

而VM的directMemory属性的值呢
 private static long directMemory = 64 * 1024 * 1024;

也就是所看到的maxMemoryValue:67108864了。这也是会把NIO的directByteBuffer的默认值认为是64M的原因了。事实并非如此:
System类的在初始化的时候会再次执行VM.maxDirectMemory(),
// Set the maximum amount of direct memory. This value is controlled
// by the vm option -XX:MaxDirectMemorySize=<size>. This method acts
// as an initializer only if it is called before sun.misc.VM.booted().
sun.misc.VM.maxDirectMemory();
这个时候的Properties已经准备好了。就会走上面if (s != null) 分支,如果有设定就会把值设定为预先设定的值。如果没有设定就会Runtime.getRuntime().maxMemory(),该方法返回的就是当前JVM最大可用的内存(不是-xmx指定的那个值,而是-xmx的值减去一个survivor区的值,因为2个survivor总有个survivor是空的,不能算在可用空间里的)。做完这个之后,会把VM类的booted属性置为true。最后获得的maxDirectMemory就是这个值。


这篇博客是对http://hllvm.group.iteye.com/group/topic/28866 讨论贴的一个总结,同时感谢R大http://rednaxelafx.iteye.com/ 不厌其烦的为我解惑。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值