JVM 学习笔记(1)

1.什么是 JVM

JVM(Java Virtual Machine),java 程序的运行环境(java 二进制字节码的运行环境)。
好处

  • 一次编写,到处运行。我们都知道java是可以跨平台运行的,这个跨平台就是实现在JVM层面,JVM对外提供了一致的运行环境。
  • 自动内存管理,垃圾回收功能
  • 数组下标越界检查(越界了就抛异常而不是覆盖其他元素)
  • 多态,JVM底层使用虚方发表实现了多态
    在这里插入图片描述

2. 内存结构

在这里插入图片描述

2.1 程序计数器

java源码会在JVM中被解析成二进制字节码,也就是一条条jvm指令,程序计数器就可以记住下一条jvm指令的执行地址,而且是线程私有的,当线程1执行到某条jvm指令时恰好被调度走了,就可以利用程序计数器来记录下一条jvm指令,当调度回来继续执行的时候,线程1就可以接着执行任务了。
除此之外,程序计数器不会存在内存溢出。

2.2 虚拟机栈

2.2.1 介绍

虚拟机栈就是线程运行时需要的内存空间,一个栈可以看作是n个栈帧组成,一个栈帧其实就对应着一次方法的调用,那么其实栈帧就是每个方法运行时需要的内存空间。,每个线程运行时纸呢能有一个活动栈帧,对应着当前正在执行的方法。

2.2.2 问题辨析

  1. 垃圾回收是否涉及到栈内存?
    不会,因为栈内存其实就是一次次方法调用产生的栈帧内存,会随着方法调用的结束自动弹出栈,也就是自动回收掉,不需要垃圾回收来管理。
  2. 栈内存分配越大越好吗
    不是,因为物理内存总量是不变的,每个线程有独立的栈,如果一个栈划分内存更大,也就意味着最大线程数就减少,降低并发。
  3. 方法内的局部变量是否线程安全?
    看一个变量是不是线程安全其实就是看这个变量是线程私有的还是每个线程共享的。
    局部变量是线程私有的并且没有超出该方法的作用域(比如说不作为返回值,这种情况针对的是引用类型变量)就没有线程安全问题,否则就可能有线程安全问题。

2.2.3 栈内存溢出

  • 栈帧过多导致栈溢出(比如递归没写好)
  • 栈帧过大导致栈溢出(基本不会出现这种情况)

2.3 本地方法栈

Java虚拟机在调用一些本地方法(Native Method)时,需要给这些本地方法提供的内存空间就是本地方法栈。本地方法就是那些不是java代码编写的方法,因为java有时候是有限制的,不能直接和操作系统底层打交道,此时java代码就可以通过本地方法间接地和底层打交道。也是线程私有的。

2.4 堆

2.4.1 介绍

通过 new 关键字创建的对象都会使用堆内存。它是线程共享的,所以堆中的对象都需要考虑线程安全问题。它有垃圾回收机制,也就是堆中没有引用指向的对象就会被当做垃圾回收掉。

2.4.2 堆内存溢出

即使有垃圾回收机制,也会出现堆内存溢出。

2.5 方法区

2.5.1 介绍

方法区(Method Area)是一块用于存储类结构信息、常量、静态变量、编译后的代码等数据的内存区域。它是线程共享的区域,用于支持JVM的运行时机制。
方法区在JVM规范中被定义为一种逻辑概念,它并不要求具体的物理实现方式。通常,方法区被实现为永久代(Permanent Generation),在旧版的JVM中,永久代是方法区的一个具体实现。然而,从Java 8开始,永久代被元空间(Metaspace)所取代,元空间也是方法区的一种实现方式。
在这里插入图片描述

2.5.2 运行时常量池

我们先来了解一下常量池,其实常量池就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息。
常量池是在*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址。

2.5.3 StringTable

简介

是用于支持字符串常量池的内部数据结构,算是字符串常量池的一种实现方式。
特性:

  • 常量池中的字符串仅是符号,第一次使用时才变成对象
  • 利用串池的机制来避免重复创建字符串对象
  • 字符串变量拼接原理是 StringBuilder的append(1.8)
  • 字符串常量拼接原理是编译期优化
  • 可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
    • java1.7 将这个字符串对象尝试放入串池中,如果串池中存在则不放入,如果没有则放入串池,会将串池中的对象返回。
    • java1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池,会把串池中的对象返回。
性能调优
  • 调整 -XX:StringTableSize=桶个数
  • 考虑是否将字符串对象入池,当有大量重复的字符串对象时,我们可以考虑将字符串入池以节省内存空间。

2.6 直接内存

直接内存不属于java虚拟机,属于操作系统内存。

  • 常见于NIO操作,用于数据缓冲区
  • 分配回收成本高,但读写性能高
  • 不受 JVM 内存回收管理
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想菜的鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值