JVM

程序 = 数据结构 + 算法

1.JVM体系结构

JVM是在操作系统上面的,使用c/c++写的,属于JRE
JVM组成:方法区(Method Area),Java栈(Java stack)、本地方法栈(Native Method)、堆(Heap)、程序计数器
JVM调优99%是在方法区和堆,其中的99%是在堆中

栈一般存放引用,放对象在堆中的地址
堆一般存放new的对象和数组
在这里插入图片描述

类的加载过程

在这里插入图片描述

类是模板(只有1个),对象是具体的(很多个)

2.双亲委派机制,主要是保证安全

类加载器:App(应用程序加载器)–>Ext(扩展加载器)–>Boot(根加载器)
双亲委派(先向上委派,再向下委派;也就是请求向上,加载向下):

  1. 类加载器收到类加载的请求,类加载器保证线程安全
  2. 将请求向上委派给父类加载器,一直向上委派,直到跟加载器
  3. 启动加载器检查是否能加载当前这个类,能加载就结束,使用当前的加载器,不行就向下通知子加载器加载
  4. 重复3,直到在App(应用程序加载器)中查找,
  5. 如果没找到就报异常ClassNotFound
  • 可以想象啃老族,父母没有才会自己动手
    如果java的同包同类名的类(String):实例化会怎么样
    报异常:找不到main方法,因为双亲委派机制(在root根加载器就查找到了这个类)

为啥程序中获取不到跟加载器的信息

  • 因为java底层是用C、C++写的,java调用不到

3.沙箱安全机制

Java安全模型的核心,限制程序运行的环境,将Java代码限定在JVM特定的运行环境中,严格限制代码对本地资源访问(主要限制系统资源访问
双亲委派机制实现沙箱安全机制

4.Native和方法区

  • 带Native关键字的,说明Java作用范围达不到了,会去调用底层C语言的库,进入本地方法栈,调用本地方法的本地接口(JNI)
  • 方法区:被所有线程共享,所有定义的方法的信息都保存在该区域,此区域属于共享区域

静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关

JNI:扩展Java的使用,融合不同的编程语言为Java所用(本地方法栈登记native方法,执行的时候通过这个调用本地方法接口JNI)

Java的本质是值传递

5.栈和队列

  • 栈:先进后出(main方法):喝多了吐
    • 主管程序的运行,生命周期和线程同步;线程结束,栈内存释放,不存在垃圾回收机制(线程级)
    • 存放:8大基本类型+对象引用+实例的方法
  • 队列:先进先出(FIFO):吃多了拉
  • 栈溢出:就是两个方法互相调用对方,一直往栈里面压,导致栈被压满了

6.堆

Heap,一个JVM只有一个堆,堆内存可以调节 (调优)
存:类、方法、常量、变量、引用类型的真实对象

分区
在这里插入图片描述

  • GC垃圾回收主要是在伊甸园区和养老区(jdk8以后永久存储区叫元空间
    在这里插入图片描述

通过代码获取堆空间大小

发现总空间=eden+old,没有meatspace的空间,即逻辑上元空间存在堆中,但物理上不存在堆中
在这里插入图片描述

GC调优主要是堆:
VM options:-Xms8m -Xmx8m -XX:+PrintGCDetails
PrintGCDetails:印GC垃圾回收信息
Xms:设置初始化内存分配大小,1/64 对应于Xmax
Xmax:设置最大分配内存:默认1/4 对应电脑内存

7、GC垃圾回收

  • 新生区:伊甸园区(Eden)、幸存0区(from)、幸存1区(to),from和to会相互转化,谁是空的谁就是to

当一个对象经过15(可设置)次GC都还没死,就会进入养老区

  • 养老区
  • 永久区(JDK8以后改成了元空间):常驻内存,用来存放JDK自身携带的Class对象,方法区,Interface元数据以及Java运行时的一些环境和类对象,不存在垃圾回收,关闭虚拟机释放内存

GC垃圾回收,主要是在伊甸园区和养老区

内存分析插件

内存快照分析工具:能看到第几行代码出错(Jprofiler,eclipse的MAT)

  • 分析Dump内存文件,快速定位内存泄露

Xms1m -Xmax8m -XX:+HeapDumpOnOutOfMemoryError

  • 打印OOM栈溢出的信息,生成profile文件
  • 获得堆中的数据及大的对象

7.题目

  • JVM的内存模型和分区~详细到每个区放什么?
  • 堆的分区:Eden、from、to、老年区,特点?
  • GC的算法?
    • 引用计数器:给每个对象都配对一个计数器,引用就+1,为0就销毁,会造成很大消耗
    • 复制算法:主要用在新生区(from和to),如果from和to都有对象,就可以把from的对象复制到to中,然后from变成to(to必须一直为空,谁空谁是to);默认值:当一个对象经历了15次gc还没死,就进入养老区
      • 好处:没有内存碎片
      • 坏处:浪费了一半内存(多了一半是to区)
      • 复制算法使用场景:对象存活率较低的区域
    • 标记清除法:对有引用的对象标记,对没有标记的对象清除
      • 优点:不需要额外的空间
      • 缺点:两次扫描,浪费时间,会产生内存碎片
    • 标记压缩:再次扫描,将存活的对象移动到一端,解决标记清除的内存碎片问题 (多了移动的成本) (再优化:多进行几次GC,再进行压缩)
没有最优的方案,永远只是时间或空间的权衡。

现在又不缺空间,所以优先复制算法

GC:分代收集算法(年轻代:复制算法,老年代:标记清除算法+压缩混合)

  • 轻GC(新生和养老区)和重GC(**和永久区)分别发生的时候?
学习新东西方法

比如说JMM

    1. 什么是JMM?
    1. 它是干什么的?
    1. 它该如何学习?
### 什么是 JVMJava 虚拟机(JVM)是 Java 运行时环境的核心组件,它负责运行 Java 程序[^2]。JVM 是一个抽象的计算机,它通过调用某个初始类的 `main()` 方法来运行 Java 程序[^3]。该方法必须满足以下条件:共有的(`public`)、静态的(`static`)、返回值为 `void`,并且接受一个字符串数组作为参数。 ### JVM 的组成 JVM 主要由以下几个部分组成: 1. **类加载器(Class Loader)** 类加载器负责将 `.class` 文件加载到内存中,并将其转换为可执行的字节码。类加载器分为引导类加载器、扩展类加载器和应用程序类加载器[^2]。 2. **运行时数据区(Runtime Data Areas)** JVM 在运行时会创建多个内存区域来存储数据,包括: - **方法区(Method Area)**:存储已被虚拟机加载的类信息、常量、静态变量等。 - **堆(Heap)**:所有对象实例以及数组都在堆上分配。 - **虚拟机栈(Java Virtual Machine Stacks)**:每个线程都有一个私有的虚拟机栈,存储局部变量表、操作数栈等。 - **本地方法栈(Native Method Stacks)**:与虚拟机栈类似,但服务于本地方法。 - **程序计数器(Program Counter Register)**:记录当前线程所执行的字节码指令地址。 3. **执行引擎(Execution Engine)** 执行引擎负责解释或编译字节码并执行。主要包括: - **解释器(Interpreter)**:逐条解释执行字节码。 - **即时编译器(JIT Compiler)**:将热点代码编译为本地机器码以提高性能[^4]。 4. **本地接口(Native Interface)** JVM 提供了与本地库交互的能力,例如通过 JNI(Java Native Interface)调用 C/C++ 编的本地代码。 5. **垃圾回收机制(Garbage Collection, GC)** JVM 自动管理内存,通过垃圾回收器释放不再使用的对象占用的内存[^2]。 ### JVM 参数与优化 为了更好地控制 JVM 的行为,开发者可以使用各种 JVM 参数进行调优。这些参数涵盖了内存分配、垃圾回收策略、线程管理等多个方面[^1]。例如: - `-Xms` 和 `-Xmx`:设置堆内存的初始大小和最大大小。 - `-XX:+UseG1GC`:指定使用 G1 垃圾回收器。 - `-verbose:gc`:输出垃圾回收的日志信息。 ### 示例代码:启动 JVM 并运行 Java 程序 以下是一个简单的 Java 程序示例,展示了如何定义一个符合 JVM 规范的入口点: ```java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } ``` 编译并运行该程序时,JVM 会加载 `HelloWorld` 类,并调用其 `main()` 方法作为程序的起点。 ### 同步与锁机制 在多线程环境中,JVM 提供了同步机制以确保线程安全。`synchronized` 关键字可以通过 ACC_SYNCHRONIZED 标志实现方法级别的同步,而无需显式调用 `monitorenter` 和 `monitorexit` 指令[^5]。 ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值