JVM简单知识了解

1. JVM组成部分

  1. 类加载器ClassLoader。类加载器通过类的全全限定名称向上请求向下加载的方式加载Class,遵循双亲委派机制。
  2. 运行时数据区RunTimeDataArea(方法区Method Area、Java栈Java Stack、本地方法栈Native Stack、堆Heap、程序计数器)。JVM内存。
  3. 执行引擎ExecutionEngine。执行class的指令。
  4. 本地方法接口NativeInterface。调用底层的C语言库。

2. JVM内存

  1. 堆:堆中是jvm中最大的一块内存区域,它是所有线程共享的,几乎所有的对象都会在堆中分配内存。
  2. 方法区:方法区也是锁有线程的共享区域,它存储了jvm加载的类的信息,常量,静态变量等数据。运行时常量池就是方法区的一部分,编译期间生成的各种字面值和服务引用就存储在其中。
  3. java栈:虚拟机栈,java中一个线程一个栈,其描述的就是线程的内存模型,也是每个线程私有的,生命周期和线程保持一致。在每个方法执行的时候,jvm会同步创建一个栈帧区存储局部变量,操作栈帧等。一个方法的生命周期就是压栈到弹栈的全部过程。
  4. 本地方法栈:java中带带有native修饰的方法代表本地方法,当调用蹦迪方法时,会进入本地方法栈。
  5. 程序计数器:每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中方法字节码,用来存储指向像一条指令的地址,也即将要指向的指令代码,在执行引擎读取下一条命令,是一个非常小的内存空间,几乎可以忽略不计。
  6. 直接内存:这部分数据不是jvm运行时数据区的一部分,nio就会使用到直接内存,也可以说是堆外内存,通常会配合虚引用一起去使用,就是为了资源的释放,会将堆外内存开辟空间的信息存储到一个队列中,然后通过GC去清理这部分空间。堆外内存优势在IO操作上,使用Socket发送数据时,能够节省堆内存到堆外内存的数据拷贝,所以性能更高。

3.堆栈的一些区别

栈是运行时单位,代表逻辑,内涵基本数据类型和堆中的对象引用,所在区域连续,没有碎片。堆时存储单位,代表着数据,可被多个栈共享,所在区域不连续,会有碎片。

  1. 栈又来存储局部变量和方法调用,而堆用来存储Java中的对象。Java变量指向的对象都是存储在堆中的。
  2. 一个线程一个栈。堆内存时所有线程共享的。
  3. 栈的空间远远小于堆内存
  4. 栈空间不足错误:java.lang.StackOverFlowError(创建的栈容量超过了Java虚拟机栈允许的最大容量)。堆空间不足错误:java.lang.OutOfMemoryError(无法申请到足够的内存去创建Java栈)。

4. 对象new的过程

当虚拟机遇到new关键字时,会判断当前类是否已经类加载,如果没有加载,首先执行类加载,加载之后再为对象分配内存空间,初始化等操作。对象创建的大致步骤:1.在堆中分配内存;2.调用构造器创建实例;3.将引用指向实例内存地址。
类加载过程:加载->验证->准备->解析->初始化。

  1. 加载:根据查找路径找到对应的class文件导入
  2. 验证:检查加载的class文件的正确性
  3. 准备:给类中的静态变量分配内存空间
  4. 解析:虚拟机将常量池中的符号引用替换成直接引用的过程
  5. 初始化:对静态变量和静态代码块执行初始化,如果存在父类,先对父类进行类加载初始化

5. 发送类初始化的情况(类的初始化一定会执行静态代码块的内容,且只有1次)

  1. 类的主动引用
  2. 虚拟机启动main方法所在的类
  3. new一个对象
  4. 访问静态成员变量或者静态方法
  5. 通过Class.forName默认情况下是加载类,可以传递参数表示不加载类
  6. 初始化一个类,父类没有初始化,先初始化父类
  • 不发生类初始化的情况
  1. 通过子类访问父类的静态域,不会初始化子类
  2. 通过数组定义类的引用
  3. 引用常量不会初始化
public abstract class People {

    static {
        System.out.println("People.class加载");
    }

    public static String getCountry(){
        return country;
    }

    public static final String country = "中国";
}

public class User extends People {

    static {
        System.out.println("User.class加载");
    }

}

public class Test {

    static {
        System.out.println("Test.class加载");
    }

    public static void main(String[] args) {
        //User[] users = new User[10];不会初始化User.class
        //System.out.println(People.country);不会初始化People.class
        //System.out.println(User.getCountry());不会初始化User.class,但是会初始化People.class
    }
}

6.双亲委派机制

类加载器自下而上分为:

  1. 用户自定义的类加载器
  2. ApplicationClassLoader应用程序加载器:加载classpath下的类
  3. ExtentionClassLoader扩展类加载器:默认加载JAVA_HOME/lib/ext目录下的jar
  4. BootStrapClassLoader启动类加载器:默认加载JAVA_HOME/lib目录下的jar
    当一个类在进行加载时,首先都会向上询问父加载器是否已经加载成功,如果没有则依次向上询问,到启动类加载器如果没有加载,则要从上向下尝试是否能加载当前类,直到加载成功。

双亲委派机制的好处:
Java中已经通过包名+类名的方式可以让一个类的名字重复。Java中所有的类默认是继承Object类,如果程序源自己定义了一个java.lang.Object类来破坏了这一情况,就导致程序在运行过程中出现问题。Java通过已经固定好的方式来加载类,防止外部类替换掉了唯一性的类。

自定义类加载器

  1. 自定义ClassLoader的子类,重写loadClass(会破坏双亲委派机制)或者findClass方法。

7. 垃圾回收算法

  1. 引用计数法
  2. 标记清除算法
  3. 标记复制算法
  4. 标记压缩算法
    引用计数法:通过计数器计算对象的使用次数,清除没有使用的对象。

标记清除算法:标记处对象垃圾,然后清除。会产生内存碎片。

标记复制算法:开辟两块完全相同的区域,对象只在其中一边区域分配,然后标记出那些存活的对象,按顺序复制到另一块
空间,案后再会后之前的空间。这样会导致内存有一半一致未使用,可用空间减少未原来的一半。

标记压缩算法:标记需要清除的对象,然后再整理存活的对象。

8.JVM调优命令及调优参数

调优命令

jps #JVM Process Status Tool,显示系统内所有HotSpot的虚拟机运行进程
jstat #JVM Statistics Monitoring,用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类加载、内存、垃圾收集,JIT编译等运行数据
jmap #JVM Memory Map命令用于生成heap dump文件
jhat #JVM heap Analysis Tool,适合jmap搭配使用,用来分析jmap生成的dump文件,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以再浏览器查看
jstack #用于生成java虚拟机当前时刻的线程快照
jinfo #JVM Configuration info,实时查看和调整虚拟机运行参数

调优参数

-Xms1m #设置初始化内存分配大小为1Mb
-Xmx9m #设置最大的内存9Mb
-XX:+PrintGCDetails # 打印GC清理详细信息
-XX:+PrintGc
-XX:+HeapDumpOnOutOfMemoryError #生成内存错误的heap dump文件
-XX:HeapDumpPath=/temp/heapdump.hprof #dump文件的地址

9.JVM为什么能跨平台

JVM的跨平台指一次编译,到处运行。Java程序编译代码之后是不能直接被系统给运行起来的,要通过系统按照Java虚拟机(JVM),由JVM来解释并允许字节码文件。对于JVM来说,不同操作系统安装方式不同,可以是JVM的最终作用时被固定好了的,class文件只与JVM打交道,它并不指定底层的操作系统是什么。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值