JVM

JVM

JVM体系结构

image
类加载器只将class文件读取到数据区中,最终是否执行还要看执行引擎.
程序计数器和计算机组成原理中的程序计数器一样,用户指向下一条运行指令.
在java中有一些方法是使用native修饰的, 比如Thread类中的sleep方法
image
这些方法实现并不是使用Java语言来进行编写的,而是C/C++实现的, Java可以直接调用实现, 本地方法库实现本地方法接口, java直接调用即可.

类加载器

类加载器类型

BootstrapClassloader: 该加载器是由c++实现的, 不允许Java获取该加载器的信息以及引用该类, 在java中获取该类加载器时会显示null, 用于加载核心类库.
PlatformClassLoader: 用于加载扩展类库.
AppClassLoader: 用于加载用户自定义的类.
类加载器是逐层递进的, 首先最上层是BootstrapClassloader 然后是PlatformClassLoader 最底层是AppClassLoader
可以使用getParent获取父 类加载器

public class Main {
    public static void main(String[] args) {
        Employee employee = new Employee();
        Employee employee2 = new Employee();
        Employee employee3 = new Employee();
        Class<? extends Employee> aClass = employee.getClass();
        ClassLoader classLoader = aClass.getClassLoader();

        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
        System.out.println(classLoader.getParent().getParent()  );
    }
}

image
类加载器首先将类进行加载初始化并生成一个类模板, 通过使用该模板实例化具体对象, 如下所示 多个类实例化对象都指向同一个模板

public class Main {
    public static void main(String[] args) {
        Employee employee = new Employee();
        Employee employee2 = new Employee();
        Employee employee3 = new Employee();

        System.out.println(employee.getClass());
        System.out.println(employee2.getClass());
        System.out.println(employee3.getClass());
    }
}

image

双亲委派机制

当类进行加载时, 首先自上向下使用类加载器进行加载, 首先会委托至最上层类加载器进行加载, 若在上层可以找到则直接进行加载操作, 下层则不会被加载. 若所有类加载器都找不到加载类则会在控制台输出错误, 比如ClassNotFoundExecption.
这样做是为了系统的安全, 避免用户更改并加载核心类库.

方法区

方法区存储类变量、静态值、类信息、final、常量池。
image

栈是以栈帧为基本单位而存储的, 栈中存储的数据类型有8大基本数据类型 对象的引用以及实例的方法. 当方法进行调用时会压入栈底, 方法调用完毕会进行弹栈操作, 然后直接执行下一个方法. 如果栈中空间不足会出现栈溢出StackOverFlowError. 栈的生命周期和线程同步, 当线程执行完毕 那么栈也就会执行完毕, 每个线程都有一个栈空间.栈顶部的栈帧就是当前执行的方法.
如果发生栈溢出, 那么一定是业务代码出现了类似方法a掉方法b, 然后方法b调a, 导致方法互相调用, 疯狂在栈中添加数据, 最后使得栈空间压爆.

一个JVM只有一个堆 类实例 变量 常量, 堆内存分为新生区 养老区 永久存储区 JDK1.7以后的永久存储区改为元空间.
新生区内又分为伊甸园区 幸存0区和幸存1区 新new的对象会进入伊甸园区 当进行垃圾回收时 没有被清理的对象会进入幸存0区 之后再进行垃圾回收时, 还是没有被清理掉的对象会进入养老区, 当养老区满了会进行重GC清理,如果重GC依旧无法解决养老区满了的问题的话,就会抛出OOM错误。
垃圾回收又分为轻GC和重GC, 轻GC主要永远清理新生区 而重GC主要用于清理养老区
如果堆内存满了会报OutMemoryError错误, 提示堆空间已满。
方法区存储在堆中

可以通关参数调整堆内存避免堆内存不足的问题。

永久区用于存储JDK本地自带的元数据,永久区

在1.6中,常量池存储在方法区中。
在1.7中 逐渐去永久代,常量池存储在堆中。
在1.8中 将永久代移除,改为元空间。

堆优化

添加堆内存大小避免OOM
-Xms:初堆内存分配大小,默认为物理内存的1/64
-Xmx: 最大分配内存,默认为物理内存的1/4
-XX:+PrintGCDetails:输出GC详细日志信息

		long maxMemory = Runtime.getRuntime().maxMemory();
		long totalMemory = Runtime.getRuntime().totalMemory();
		System.out.println(maxMemory / (1024 * 1024));
		System.out.println(totalMemory / (1024 * 1024));

GC

引用计数法

设置一个计数器,当对象被引用时计数器 + 1, 当对象引用失效时计数器 - 1当计数器为0时清除该对象
优点: 容易实现, 判定率高
缺点: 无法解决对象循环引用的问题.

复制算法

posted @   RainbowMagic  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示