JVM入门学习

 

一引言

在面试中Java虚拟机JVM的相关知识是必须会被问到的,如下面几个问题,

  • 谈谈对JVM的理解
  • 谈谈对JVM中的ClassLoader类加载器的理解,JVM是怎么加载class文件的?
  • 什么是OOM?什么时候会出现StackOverFlowError和OutOfMemoryError,写代码实现一下?
  • JVM的常用参数调优了解吗?
  • 内存快照抓取和MAT分析hprof文件干过吗?
  • 谈谈垃圾回收机制
  •  .........

所以很有必要好好学习以下JVM相关的知识

 二基本

什么是JVM?

是JAVA虚拟机,是一种用于计算设备的规范,是虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的(百度百科)。

JAVA语言最大的一个特点是与平台的无关性,而JVM是实现这一特点的关键。

JVM运行在操作系统之上,与硬件没有直接的交互。

 

三类加载

JVM把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,形成可以被JVM直接使用的java类型的过程。

类加载过程:加载->验证->准备->解析->初始化。

类加载器:

  • BootStrap ClassLoader:启动类加载器,c++实现,负责加载存放在\lib下的class文件,或者被-Xbootclasspath参数所指定的路径中的
  • Extension ClassLoader:扩展类加载器,负责加载\lib\ext路径下的class文件
  • Application ClassLoader:应用类加载器,负责加载用户类路径(classpath)上所指定的class文件,

双亲委派模型,要求除了顶层的启动类加载器外,其他的类加载器必须有父类加载器。

双亲委派加载过程:当一个类加载器收到加载类的请求时,先把这个请求委派給父类加载器完成,只有当父类加载器无法完成加载任务时,才由子类加载器尝试加载。

这样设计的好处是什么?

 

四jvm运行时内存数据

4.1 PC寄存器

每个线程都有一个程序计数器,是线程私有的。

4.2 栈

在线程创建时创建,生命周期跟随线程的生命周期,线程结束栈内存也会释放。

模拟一个StackOverFlowError:

 1 package cn.np.jvm;
 2 
 3 /**
 4  * @author np
 5  * @date 2018/9/10
 6  *
 7  * 实验StackOverFlowError
 8  */
 9 public class StackOverFlowErrorDemo {
10 
11     public void func(){
12         func();
13     }
14 
15     public static void main(String[] agrs){
16         StackOverFlowErrorDemo stackOverFlowErrorDemo=new StackOverFlowErrorDemo();
17         stackOverFlowErrorDemo.func();
18     }
19 }

4.3 方法区

各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

  • Java虚拟机规范把方法区描述为堆的一个逻辑部分
  • 有一个别名叫非堆
  • 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常

 


4.4 堆

对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。这一块内存区域被所有线程共享,是在虚拟机启动时创建。

  • 存放对象实例,几乎所有的对象实例以及数组都在这里分配内存
  • 垃圾收集器管理的主要区域
  • 物理上可以是不连续的内存空间,逻辑上是连续的
VMoptions:-Xms256m -Xmx256m -XX:+PrintGCDetails

-Xms: 设置初始分配大小,默认为物理内存的 1/64

-Xmx:最大分配内存,默认为物理内存的1/4

-XX:printGCDetails:输出详细的gc处理日志


public class HeapDemo {

    public static void main(String[] agrs){
        long maxMemory=Runtime.getRuntime().maxMemory();
        long totalMemory=Runtime.getRuntime().totalMemory();

        System.out.println("maxMemory="+maxMemory+"字节,"+(maxMemory/(double)1024/1024)+"MB");
        System.out.println("totalMemory="+totalMemory+"字节,"+(totalMemory/(double)1024/1024)+"MB");
    }
}

 

 

 

posted @ 2018-09-10 21:09  @希望就在前方  阅读(72)  评论(0编辑  收藏  举报