`

从一个例子看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/ 不厌其烦的为我解惑。
分享到:
评论

相关推荐

    深入JVM内核 - 原理、诊断与优化

    介绍了Java堆的分析方法,以一个实例为基础,展示对堆的分析过程。 第九课 锁 baise锁 轻量级锁 自旋锁 介绍JVM中对多线程锁的实现。 第十课 class文件结构 ASM库介绍 介绍JVM规范中的最重要的内容——Class文件...

    JVM实战-JVM类加载机制案例分析

    在这个例子中,`Singleton`类采用单例模式,确保了在整个程序运行期间只有一个实例存在。通过调用`getInstance()`方法来获取该实例,从而触发类的初始化过程。 **运行结果分析与总结**:通过观察上述程序的执行结果...

    jvm 加载class文件

    在Java环境中,每个类(Class)以及接口(Interface)都会对应一个`.class`文件,这些文件构成了Java程序的基本执行单元。由于Java的动态性,只要修改了类中的成员变量或者方法,相应的`.class`文件就会发生变化,这...

    jvm常用命令工具

    为了更好地理解上述工具的使用方法,下面提供了一个示例代码片段: ```java package com.leanworld; import java.util.ArrayList; import java.util.List; public class JVMTools { public static void create...

    用JVM工具接口创建调试和分析代理.docx

    Java虚拟机工具接口(JVMTI,Java Virtual Machine Tool Interface)是Java开发工具包(Java SDK)的一个核心组件,自Java 2 SDK Standard Edition 1.5.0版本起引入,用于替代实验性的JVMPI(Java Virtual Machine ...

    JVM崩溃

    在这个例子中,我们看到的`hs_err_pid340.log`就是这样一个日志文件。 首先,我们需要了解JVM的工作原理。JVM是Java语言的核心组成部分,它负责解析和执行Java字节码,提供内存管理、垃圾回收、类加载等功能。当JVM...

    weblogic扩展JVM扩容

    在这个例子中,我们设置了初始堆内存和最大堆内存均为4GB(4096M)。 ##### 3. 重启WebLogic服务 完成内存配置修改后,需要重启WebLogic服务使新设置生效。 #### 五、注意事项 - 在修改内存配置之前,请确保对...

    jvm基础学习,介绍各种jvm里面的知识点,和深入理解java虚拟机很像,易懂

    每当执行一个方法时,就会为该方法分配一个新的栈帧,其中包含局部变量表、操作数栈、动态链接和方法返回地址等。 2. **堆**:是所有线程共享的内存区域,用于存储对象实例。新创建的对象通常放置在新生代(Eden区...

    JVM基础知识

    考虑一个具体的例子: - `-server`: 指定使用Server模式,通常适用于长时间运行的服务端应用。 - `-Xmx2g`: 设置最大堆内存为2GB。 - `-Xms2g`: 设置初始堆内存也为2GB。 - `-Xmn256m`: 设置年轻代内存为256MB。 - ...

    半栈工程师.JVM之模板解释器 - 知乎1

    在JVM启动时,这些汇编代码被编译成机器指令并存储在内存中。当执行字节码指令时,JVM可以直接跳转到对应的机器指令地址,从而提高了执行效率。 模板解释器的创建涉及到几个关键步骤: 1. **模板的初始化**:JVM中...

    dubbo入门例子程序

    【Dubbo入门例子程序】是针对初学者设计的一个简单示例,旨在帮助理解并快速上手Apache Dubbo这一高性能、轻量级的Java远程服务框架。这个例子通过一个"Hello, World!"的应用来演示Dubbo的基本用法,采用Maven作为...

    深入Java虚拟机JVM类加载学习笔记

    1. 如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把请求委托给父类加载器完成。 2. 父类加载器如果无法完成加载,则会返回给子类加载器,由子类加载器尝试加载。 3. 这种机制可以确保...

    JVM核心教程之JVM运行与类加载全过程详解

    以下是一个简单的示例,展示了类加载过程: ```java public class Demo01 { public static void main(String[] args) { A a = new A(); System.out.println(a.width); } } class A { public static int width...

    RMI学习例子

    远程方法调用(Remote Method Invocation,RMI)是Java平台中的一个重要特性,它允许一个Java对象调用在不同JVM(Java虚拟机)上的另一个对象的方法。在这个“RMI学习例子”中,我们有两个关键部分:服务端和客户端...

    Java 链接 R 软件的一个例子

    在Java端,我们需要一个名为`RInside`的库,它是`rJava`的一个包装器,简化了在Java程序中创建和管理R实例的过程。`RInside`提供了方便的API,用于在Java代码中创建R实例、执行R命令、读写R变量等。为了使用`RInside...

    使用Jconsole对java的内存使用情况(JVM)进行监控.pdf

    监控过程涉及到在Linux环境下配置Resin应用服务器,需要添加JVM启动参数来启用远程JMX访问,包括设置监听端口、密码文件和访问控制文件。默认的用户名和密码为“monitorRole”和“controlRole”,并可以通过编辑...

    main方法启动服务

    在这个例子中,`main`方法创建了一个`ServerSocket`,监听8080端口。当有客户端尝试连接到这个端口时,服务器就会接收到请求并进行处理。当然,实际的服务启动过程会更复杂,可能涉及线程管理、请求处理、数据库连接...

    servle的第一个例子.docx

    ### Java Web 第一个例子知识点详解 #### 一、实验目的及要求 1. **掌握动态Web工程的创建,以及动态Web工程目录结构与Java工程的区别** - **动态Web工程的创建**: - 使用IDE(如Eclipse或IntelliJ IDEA)创建...

    java RMI 例子

    3. **启动服务器**:在服务器端,我们需要一个主类(如`RmiServer.java`)来创建`MyRemoteImpl`的实例,并使用`Naming.rebind()`将它绑定到RMI注册表。例如: ```java MyRemoteImpl remote = new MyRemoteImpl(); ...

    rmi简单例子,可以学习一下

    RMI(Remote Method Invocation,远程方法调用)是Java平台中的一个重要特性,它允许Java对象在不同的Java虚拟机(JVM)之间进行通信,从而实现分布式计算。在"rmi简单例子,可以学习一下"这个主题中,我们将深入...

Global site tag (gtag.js) - Google Analytics