JVM超详细解析

17 篇文章 4 订阅
订阅专栏

一、初始JVM

1. JVM 需要了解的三个方面

a)JVM中的内存布局是怎么样的,它们分别的作用是什么?
b)JVM中的类加载的过程是怎么样的,具体步骤?
c)JVM中的垃圾回收机制(GC)有什么优缺点,涉及到的回收机制和算法有什么?

下面我们就来一一探讨这三个问题。

2.常见的虚拟机

JVM,说是叫“虚拟机”,但是对比VMware和Virtual Box 虚拟机来说,并不是同一回事。JVM只是对硬件设备进行了简单的抽象封装,能够达到跨平台的效果。而VMware和Virtual Box 是100% 使用软件来模拟出真实的硬件。

还有HotSpot VM,是Oracle官方和开源OpenJDK 都是用这个虚拟机的。

二、JVM的内存布局

1.内存的划分

JVM划分的区域:
1.堆
2.栈
3.方法区
4.程序计数器

JVM实际上是一个Java 进程,进程就是用来管理硬件资源的,比如内存。JVM启动之后就会从操作系统这里申请到一大块内存

具体的内存布局:
在这里插入图片描述
对于堆区和方法区,在整个JVM中只存在一份,而程序计数器和栈区是跟进程绑定在一起的,每个不同的线程都有独立的一份程序计数器和栈区。

不同的区域放不同的东西
1.堆中放入的是 new 的对象。(不要忘了在JDK 1.8中,字符串常量池在堆中)

2.方法区放入的是 类对象。
.java->.class->JVM就会把.class文件进行加载,加载到内存中,最后变为类对象。
类的static 成员,作为类属性。同样也是在类对象当中的,就放到方法区里。

类对象里有什么?
a)包含这个类的各种属性的名字,类型,访问权限。
b)包含这个类的各种方法的名字,返回值,访问权限,参数类型,以及方法的实现的二进制代码。
c)包含这个类的static 成员。

方法区内部有个运行时常量池,存放字面量和符号引用:
字面量 : final常量、基本数据类型的值。
符号引用 : 类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符。

3.栈区放入的是 局部变量。
对于什么变量放在栈区,什么变量放在堆区,跟它是引用类型还是内置类型无关,只要取决于它是在内存中的哪个区域,是全局变量(成员变量),还是局部变量,还是静态变量?
Java虚拟机栈:给上层的Java代码来使用的。
本地方法栈:本地方法栈是给本地方法使用的。

4.程序计数器放入的是 内存地址。
这个内存地址的含义是,接下来要去执行的指令地址。
我们写的.java 文件 -> .class 文件 ->读到内存当中 -> 每个指令都有自己的地址 -> CPU要执行指令就需要从内存中去取地址,然后再在CPU上执行。

2.和内存区域相关的异常

1.堆溢出,代码中出现堆溢出的话就会抛出“java.lang.OutOfMemoryError”,典型的情况就是不断地去new 对象而不去释放内存。
2.栈溢出,代码中出现栈溢出的话就会抛出“java.lang.StackOverflowError”,典型的场景就是不断去递归不带有终止的if条件。栈里面除了要放局部变量外,还要放方法的调用关系。

堆和栈的空间大小,都可以通过JVM(Java进程的命令行参数)来进行配置。
在这里插入图片描述

3.根据代码判断该变量在JVM的哪个内存中

a)下面代码doGet方法中的test是在哪个内存区域?

class Test {
    public int val = 0;
}
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Test test = new Test();
    }
}

答:Test test = new Test();中的test是一个局部变量,因此是存放在栈区中的,而new 出的对象就是放在堆区中。
在这里插入图片描述
b)下面代码Test test = new Test();是在哪个内存区域?

class Test {
    public int val = 0;
}
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    Test test = new Test();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

答:因为HelloServlet这个类是需要new出来的,对应地对象里面就有test引用及其对象。t是一个全局变量,因此是在堆中的,后面new 出来的对象,也是在堆中的。在这里插入图片描述
c)下面代码中static Test test = new Test();存放于内存的哪个区域?

class Test {
    public int val = 0;
}
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    static Test test = new Test();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

答:因为Test test = new Test();是被static关键字修饰了,因此t变成了静态成员变量,此时t就是在类对象中,即方法区当中。而new 出的对象不变,仍然存放在堆中。在这里插入图片描述

4.引用类型的理解

我们可以把引用类型当作一个“低配指针”,但从更严谨的角度去看,引用并不是一个指针。Java的引用相当于堆C语言的指针功能进行了裁剪,Java中的引用只能用来解引用(如:使用 . 就是默认地解引用)和比较(==或!=) 。

三、Java的类加载

1.有关.class文件的格式规范

类加载其实是JVM 中的一个非常核心的流程,做的事情,就是把.class 文件,转成JVM 中的类对象

要想完成 类加载,必须要明确的知道,.class文件中都有啥,按照.class文件中的规则进行解析。因此,编译器和类加载器(JVM)必须要商量好.class文件的格式。而.class 文件的格式,在 JVM虚拟机规范文档 里面已经约定好了的,则编程语言的语法,也可以理解为一种“协议”。

发明/定义一个编程语言,就一定要让该编程语言跑起来,就需要把源码编译成可执行程序,再进行执行。过程:编译->.class->加载 。

在JVM虚拟机规范文档中有:
上面的是Java语法规范,是约束编译器和程序员之间的。下面的是Java虚拟机规范,是约束编译器和JVM 之间的。
在这里插入图片描述
我们可以选择HTML 的文档格式去查看,第二章的第一节就是有关.class文件格式的规范。而点进去又会提示你在第四章中才会有…

u4就是一个无符号四个字节的整数,u2就是两个字节的无符号整数。而带有info的都是结构体。可以看到,它把java代码中,定义的一个类的核心信息都体现进去了,只不过这个文件的格式是二进制的。
在这里插入图片描述
因此,根据上述的格式,我们可以自己开发一个编程语言,然后编译就根据.class文件的格式一样,就可以直接在JVM中去解析执行了。
这样就大大地降低了语言开发的成本,如Kotlin,Scala,Groovy等语言都是基于JVM体系的语言。因此,Kotlin就能够和Java无缝对接,非常方便地去使用Java现有的生态,对比Java,含有的语法糖更多一些。它是有更多现代一些编程语言的特点。

2.类加载的基本流程

类的生命周期:都离不开.class文件的格式
在这里插入图片描述
加载:目的是把.class 文件给找到。如果代码中需要加载某个类,就需要去特定的目录下去查找该.class文件,找到之后,就需要打开这个文件,并且读取这个文件。此时这些数据就已经读到内存里了。

验证:目的是验证后缀为.class 的文件是否是编译器编译生成的,如果是人为地去改后缀变为.class 的文件,那么就不是一个合法的.class 文件。除了验证.class 文件的格式外,还需要验证文件里面的字节码指令是否正确。(方法里面具体要执行的指令)

准备:目的是为类对象中的一些成员变量分配内存空间(静态变量…),并且进行一个初步的初始化(初始空间大小为0).

解析:主要是针对字符串常量进行的处理。.class文件涉及到一些字符串常量,在解析的过程中,就把这些字符串常量替换成当前JVM中的字符串常量。
注:不是程序一启动,就把所有的类都加载完毕的,而是用到哪个类就加载哪个类,而字符串常量是最初启动JVM的时候就有的。

初始化:主要针对在“准备”环节中,对初步初始化的静态变量进行真正地初始化。同时也会执行static 的代码块。

前面两个过程是重要理解的

针对上述JVM类加载过程,有个代码需要注意一下:
在这里插入图片描述
我们发现结果是:(由父及子,静态最先)
在这里插入图片描述
原因:当new B() 的时候,就会先尝试去加载 B 这个类,然后加载B 的时候,因为是B 继承于A ,于是又得先加载A 。等到两个类都加载完了,再进行实例化的操作

3.类加载中的双亲委派模型

双亲委派模型,是类加载中的加载环节里面的很小的一部分细节。更准确地说,应该叫“父亲委派模型”。

在进行类加载的过程中,其中一个非常重要的环节,就是根据这个类的名字(如:java.lang.String) 找到对应的.class 文件。
在JVM中,有三个类加载器(三个特殊的对象)来负责找文件的操作。这三个类加载器对象都有各自找的区域。

图示如下:
在这里插入图片描述
这三个类加载器之间存在父子关系(但并不是继承中的父子关系,而是类似于链表一样,每个类里面都有个 parent 字段,指向了父类加载器)。

双亲委派模型的流程
当代码中使用到某个类的时候,就会触发类加载。首先是从AppClassLoader 开始的,但是AppClassLoader 并不会直接开始去扫描自己负责的目录,而是先找它的爸爸。找到了ExtClassLoader 之后,它也一样,不会立刻去扫描自己负责的目录,而是又去找它的爸爸。
找到BootStarp 之后,它也不会立刻去扫描自己负责的目录,而去找它的爸爸。但是它并没有爸爸,因此就只能自己先去扫描自己负责的目录。如果在自己的目录中,找到了复合的类,就没有其它类加载器的事情了。但是如果没有找到匹配的类,就告诉儿子(ExtClassLoader)。
ExtClassLoader再来找自己负责的目录,如果找到,就加载,找不到就告诉儿子(AppClassLoader)去查找。
AppClassLoader就在自己负责的目录去查找,如果找到就加载,找不到就抛出ClassNotFound异常。

这里有这么一套规则,其实就是在约定上述被扫描的目录的优先级。这个优先级在正常情况下没有什么作用,假设如果是我们自己创建了一个java.lang.String 的类(只有一个类),同时有标准库中的String 类。那么有优先级后,就会先去加载标准库中的String类,因为我们创建的类是一个复合类,因此就没有其它加载器的事情了。

4.双亲委派模型的优点

1.避免重复加载类:比如 A 类和 B 类都有一个父类 C 类,那么当 A 启动时就会将 C 类加载起来,那么在 B 类进行加载时就不需要在重复加载 C 类了。
2.安全性:使用双亲委派模型也可以保证了 Java 的核心 API 不被篡改,如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类,而有些 Object 类又是用户自己提供的因此安全性就不能得到保证了。

5.破坏双亲委派模型

我们学了Servlet后,知道里面根本就是没有main方法的,而且很少会涉及到标准库中的类,一般涉及的类都有Servlet相关。因此Tomcat 的webapps 中就有很多的类,是Tomcat 内部自己实现的类加载器来完成的(目的是告诉程序去额外的目录去找.class)。则Tomcat就没有去遵守 双亲委派模型。

四、垃圾回收机制(GC)

1.什么是垃圾回收?

垃圾回收,回收的是内存。JVM 其实是一个进程(java),一个进程会持有很多的硬件资源,如(CPU,内存,硬盘,带宽),而系统的内存总量,是一定的。因此对内存的合理使用是非常重要的。
内存要经过:申请->使用->释放 过程。内存是有限的,并且要给很多的进程去使用。从代码编写的角度看,内存申请的时机是很明确的,但是内存的释放时机很模糊。对于C语言来说还好,内存的释放是靠程序员自己去手动释放的,如malloc、free等。但是一旦忘了释放内存,就会造成内存泄漏,直到内存耗尽为止。

对于内存泄漏问题,不同的语言有了不同的解决方法:在C++中引用了智能指针,在合适的时机去自动释放内存,(一般是通过引用计数的方式来衡量这个内存被引用了多少次,当引用计数为0时就真正释放内存)。在Rust中,采取的方案是基于语法上的强校验,Rust引入了很多对内存操作相关的语法规则,在编译器编译期间就会对进行严格的检查和校验,一旦发现有代码存在内存泄漏的风险,就编译报错。但是也有不好的地方,它的语法非常丑陋,同时也限制了很多功能的实现。以至于在实现一些特殊功能的时候,要使用个’unsafe’操作,引入这个操作,之前的校验也就部分的失效了。

而Java中采用垃圾回收的方式,对于该机制来说,哪一个代码申请都可以,哪里申请都可以,都是由JVM统一去进行垃圾回收(内存释放),具体来说,就是由JVM 内部的一组专门负责垃圾回收的线程来进行这样的工作。

优点:能够非常好地保证不出现内存泄漏的情况(不是100%保证),并且是自动去进行内存释放。
缺点:
1.需要消耗额外的系统资源。
2.内存释放可能存在延时(不是内存不用了就马上回收,可能过段时间才会回收)
3.可能会出现STW 问题(stop the world),比如说有一大段内存需要去释放,那么可能系统的资源都用来去释放该内存了,而其它的代码就不能够继续执行,没法去做别的事情了。但是现在大佬们能够将STW 问题限制在了1ms 之内。

2.Java的垃圾回收要回收的内存是哪些?

JVM中有四个区域:堆区、方法区、栈区、程序计数器。堆区里面的内存就主要是JVM需要释放的内存对象。而方法区里面的是类对象,它是类加载过来的,而对方法区进行垃圾回收,就相当于“类卸载”,这里的规则比较特殊,我们不用考虑。而栈区和程序计数器是跟进程绑定在一起的,在进程结束的时候,相应地,栈区里面的变量和程序计数器就会随之自动释放内存空间了。

在上述几个区中,堆占据的内存空间就是最大的,本来就是占据了一个程序的大部分内存

3.回收堆上的内存,具体回收的是什么?

堆内存中,可以划分为:
在这里插入图片描述
垃圾回收机制主要回收的就是 完全不再使用的内存。对于一半在使用,一半不再使用的内存,是不回收的,因为回收的成本比较大,当然实现起来也比较麻烦。

因此,Java中的垃圾回收,是以“对象”为基本单位的,一个对象,要么被回收,要么不被回收,不会出现一个对象被回收一半的情况。

4.垃圾回收到底是如何回收的?

垃圾回收的基本思想:先找出垃圾,再回收垃圾。因此,就要确保该某个对象不再被使用,就认为是垃圾。如果要是把正在使用的对象回收了,就会造成很严重的后果了。

如:一个游戏服务器,提供服务,其中有一个功能,玩家查询自己的账户余额。查询的时候肯定是需要把查询的结果保存到一个对象中,当用户尝试获取到这个结果的时候,结果对象正常来说会包含结果数据,但此时被回收了,此时查询的结果就是一个错误的结果。

因此相比于回收少了,回收多了(回收错了)是一个更严重的问题,对于GC 来说,级别垃圾的原则,宁可放过也不要乱回收。

5.如何找到垃圾?

如何找垃圾也可以称为(如何标记垃圾?/ 如何判定垃圾?) 。抛开Java来说,单纯GC 的话,判定垃圾有两种典型的方案。
a)引用计数
b)可达性分析

5.1 引用计数

先谈谈 引用计数:
引用计数,就是通过一个变量来保存当前的这个对象,被几个引用来指向。一个对象就会内置一个计数器记录它被几个变量所指向。

如:此时new Test() 这个对象就被三个变量所指向,因此里面的计数器就为3.

Test a = new Test();
Test b = a ;

func(a);
void func(Test t) {
  ...
}

但是引用计数有个致命的问题。当出现循环引用时:如:

class Test {
   Test t = null;
}

Test t1 = new Test();//1
Test t2 = new Test();//2
t1.t = t2;//3
t2.t = t2;//4

t1=null;//3
t2=null;//2

当代码运行完t2=null 的时候,按引用计数的情况来说,new Test() 里面的计数器为2,但是此时内存是不再使用的,它不被回收就会导致内存泄漏了。

因此,引用计数的优缺点:
优点:规则简单,实现方便,比较高效(程序运行的效率高)。
缺点:
1.空间利用率比较低(比较浪费空间,尤其是针对大量的小对象)。本来引用的次数就不多,而且还内置了计数器就比较浪费空间了(每一个int占4个字节)。
2.存在循环利用导致判定是否是垃圾出现了错误,从而无法回收。

因此在Java中没有使用引用计数去判定垃圾,而是第二种方式——可达性分析。

5.2 可达性分析

从一组初始位置出发,向下进行深度遍历,把所有能够访问到的对象都标记成“可达”,对应地,没有访问到(不能访问到) 的对象就没有标记,没有标记的就是垃圾

如:
在这里插入图片描述
有:

class TreeNode {
   char val;
   TreeNode left;
   TreeNode right;
}

TreeNode root = ...;

假设root 是一个方法中的局部变量,当前栈帧中的局部变量,也是进行可达性分析的一个初始位置,从此处就往下进行遍历。
默认情况下,整棵树都是可达的,都不是垃圾,但是如果有root.right.right=null,则f这个结点就不可达了,就成了垃圾。如果有root.right=null,此时c和f结点都不可达了,就都是垃圾了。

JVM中采取的方案是:在JVM 中就存在一个/一组线程,来周期性地,进行上述遍历的过程,不断地找出这些不可达的对象,由JVM进行回收。

可达性分析的初始位置有
1.栈上的局部变量表中的引用。
2.常量池里面的引用指向的对象。
3.方法区中,引用类型的静态成员变量。

基于上述过程,就完成了对垃圾的标记。和引用计数相比,可达性分析,确实更麻烦,同时实现可达性分析的遍历过程开销是比较大的。但是带来的好处是解决了引用指针的两个缺点:内存上不需要消耗太多的空间,也没有循环引用的问题。

不管是引用计数还是可达性分析,我们都可以发现,内存是否需要回收 是看 当前的对象是否有引用来指向。是在通过引用来决定对象的生死。

6.找到垃圾后如何去回收?

垃圾回收中的经典算法/策略:
a)标记-回收
b)复制算法
c)标记-整理

6.1 标记-回收

比如说:白色是正在使用的对象,灰色是已经被释放的空间。
在这里插入图片描述
虽然此处可以释放掉不再使用的内存空间,但是引入了一个问题——内存碎片。我们发现,空闲的内存和正在使用的内存,是交替出现的。

此时如果是申请一小块内存,那没什么问题。但如果是申请一大块连续的内存,此时可能就会分配失败。很多时候,申请的内存,是一块连续的空间(new byte[]),由于内存碎片的存在,整个空闲的内存有100M,此时申请50M的内存,仍然可能会分配失败。

内存碎片的问题,如果一直累计下去,就会导致:空闲的内存其实挺多的,但是不能够去使用,就很难受了。并且该问题在频繁地“申请释放” 的场景中更加常见。

6.2 复制算法

它是为了解决 标记-清除 的内存碎片问题的。把内存分为两部分。
开始:
在这里插入图片描述
此时假设1、3要被回收,那么就剩下了2,4了。就将2,4的内存复制到右遍的内存区域中。此时再回收掉左边的一整个内存区域。内存区域一次只用一个部分。
在这里插入图片描述
使用复制算法,就能够解决 标记-清除 内存碎片问题。
复制算法的缺点:
1.可用的内存空间,只有一半。
2.如果要回收的对象比较少,而剩下的对象比较多,复制内存的开销就很大了。

因此复制算法,适用于:对象会被快速回收,并且整体的内存不大的场景下。

6.3 标记-整理

能够解决复制算法的内存空间利用率的问题。它类似于顺序表的“删除”的搬运操作。
初始:假设此时要回收2,4,6 的内存空间。
在这里插入图片描述
就将3往2搬,因为4是需要回收的,它不动。5往第三个位置搬,6是需要回收的,不动。7往第四个位置搬,8往第五个位置搬。搬到最后6没有被覆盖,那么就回收6 。

最终结果:
在这里插入图片描述
这样的操作,能够有效避免内存碎片,同时也能提高内存利用率。
缺点:在搬运的过程中,是一个很大的开销,这个开销可能比复制算法里面的开销更大

6.4 分代算法

实际实现的垃圾回收算法,要能够结合上面的三种方式,取长补短。就有了分代算法。

它把内存中的对象分成了几种情况,每种情况下,采用不同的回收算法。

根据“年龄”去进行划分。年龄是如何来的?是根据GC 的次数来的,每次经历一个扫描周期,就认为“长了一岁”。在JVM中,垃圾回收扫描(可达性分析)是周期性地进行的。因此就根据不同的年龄,就采用不同的垃圾回收算法来处理了。

划分结构:
在这里插入图片描述
分代回收的过程:
1.一个新的对象,诞生于伊甸区。
2.如果活到一岁的对象(对象经历了一轮 GC 还没死),就拷贝到 生存区。

生存区的内存大小比较小,那么空间小能放下这么多对象吗?
答:根据经验规律,伊甸区的对象,绝大部分都是活不过一岁的,只有少数对象能够来到生存区,对象大部分都是“朝生夕死”的。注意:是大部分!!!

3.在生存区中,对象也要经历若干轮GC,每一轮GC 逃过的对象,都通过 复制算法 拷贝到另外的生存区里。这里面的对象来回拷贝,每一轮都会淘汰掉一批对象。

4.在生存区中,熬过一定轮次的GC 之后,这个对象如果还没有被回收的话,JVM就认为,这个对象未来能够更持久地存在下去。于是就将这样的对象拷贝到老年代了。

5.进入老年代的对象,JVM都认为是属于能够持久存在的对象。这些对象也需要使用GC 来扫描。但是扫描的频次就大大地降低了。老年代这里通常使用的是标记-整理算法。

特殊地,如果一个对象的内存特别大,它会直接放入老年代。因为如果把它放入到新生代,如果经过一轮GC没有被淘汰,就放到生存区中。在生存区中拷贝来拷贝去的开销会比较大,甚至有的对象的内存太大在生存区可能放不下,因此直接放入老年代更合适。

6.5 垃圾回收器(了解)

垃圾回收器,属于JVM 中GC 机制的具体实现。这些具体实现中,就应用到了上述的一些垃圾回收算法。

我们真正需要了解的有两个垃圾回收器。
1.CMS 。最主要的特点,是尽可能地降低STW ,使用标记-回收,先进行一个初步的标记(很快,会出现STW),接下来和业务线程并发的进行 深入的标记(不会STW),再进行一个重新的标记(很快,但是会STW),主要是对之前的标记进行简单地修正,最后进行回收。

2.G1 。最主要的特点,是将内存划分成了更多的小区域(不像上面所说的新生代和老年代),以小区域单位进行GC 。

JVM 详细解读
peiuuu的博客
03-16 1446
JVM运行机制、内存模型、垃圾回收、类加载机制
JVM面试掌握这些,就稳了
weixin_49114080的博客
10-10 280
Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域, 这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有 些区域则是依赖用户线程的启动和结束来建立和销毁。Java虚拟机所管理的内存包括 以下几个运行时数据区域,如图: 1、程序计数器:指向当前线程正在执行的字节码指令。线程私有的。 2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈
一篇文章掌握整个JVMJVM详细解析
Admans的专栏
04-26 75
程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC)。GC是不定时去堆内存中清理不可达对象。不可达的对象并不会马上就会直接回收, 垃圾收集器在一个Java程序中的执行是自动的,不能强制执行清楚那个对象,即使程序员能明确地判断出有一块内存已经无用了,是应该回收的,程序员也不能强制垃圾收集器回收该内存块。
JVM分析(附GC的有关知识)
hulin的博客
05-16 634
一、JVM的基本概念 1.JVMJava虚拟机,用来保证Java语言跨平台。 2.JVMJava语言并没有必然的联系,他只与特定的二进制文件格式(class文件格式相关联) 3.JVM就是一个字节码翻译器,它将字节码文件翻译成各个系统对应的机器码,确保字节码文件能在各个系统正确运行。 二、JVM存在的意义 先想一个问题:电脑是怎么认识我们所编写的Java程序的 首先要明白电脑是二进制的系统,它只认识 机器码(二进制编码),例如01010... 比如我们经常要编写 的文件名.java...
2024年Web前端最全【经验分享】显示文件扩展名,一个三非渣本的前端校招秋招之路
2401_84438654的博客
05-04 342
面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】前端面试题汇总JavaScript前端资料汇总如何在.java文件和记事本之间通过改扩展名快速切换呢?首先打开此电脑(我的电脑)找到左上角的这个东西。
一篇文章掌握整个JVMJVM详细解析!!!
12-21
JVM先想想一些问题1 我们开发人员编写的Java代码是怎么让电脑认识的2 为什么说java是跨平台语言3 Jdk和Jre和JVM的区别4 为什么要学习JVM深入学习JVM1 JVM运行时数据区2 解析JVM运行时数据区2.1 方法区(Method Area...
Java详细基础知识学习文档
06-19
1. Java虚拟机(JVM):JVMJava程序的核心执行引擎,它负责解析和执行字节码,并管理内存、寄存器和数据。JVM的设计使得Java程序能够在多种操作系统上无缝运行。 2. JDK与JRE:JDK(Java Development Kit)是Java...
详细Java程序员的系列教程,从0学习Java
最新发布
05-08
详细JAVA系列教程 Java基础面试题 操作系统 计算机基础知识 深入理解计算机系统 优质 github 推荐 HTTP 系列 汇编语言 C 语言 计算机网络 Java 基础教程 设计模式 JVM 并发 Spring 框架系列 Spring SpringMVC ...
使用HOCON文件的JVM语言配置库-python
06-18
对“嵌套”的良好支持(将配置的任何子树视为整个配置)用户可以使用 Java 系统属性覆盖配置,java -Dmyapp.foo .bar=10 支持配置应用程序及其框架和库,所有这些都来自单个文件,例如 application.conf 解析持续...
JVMJVM内存模型详解
Money、坤的博客
08-24 1万+
JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。方法区存储的内容有:类型信息(比如类全称、父类全称)、域信息(域名称、域修饰符private等)、方法信息(方法名称、方法修饰符、返回类型等)、字面量(字面量包括文本字符串、八种基本类型的值 、被声明为final的常量等)。Java虚拟机栈是当前线程在执行方法时存储所需的数据、指令、返回地址的一种栈结构(先进后出)。
JVM深入讲解,很不错的学习资料
04-06
NULL 博文链接:https://huashuizhuhui.iteye.com/blog/1545736
java虚拟机详细讲解
03-31
java虚拟机java虚拟机java虚拟机java虚拟机java虚拟机java虚拟机
Java | JVM | 详细图解,坚持看完,带你真正搞懂Java虚拟机
【CSDN】
11-22 1万+
Java虚拟机 1、JVM简介 JVM 是可运行 Java 代码的假想计算机 ,包括<mark style=“margin: 0px; padding: 0px;”>一套字节码指令集、一组寄存器、一个栈、 一个垃圾回收,堆和 一个存储方法域。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。</mark> 我们都知道 Java 源文件,通过<mark style=“margin: 0px; padding: 0px;”>编译器</mark>..
JVM 详解
Tiny_Guo的博客
03-09 246
文章目录JVM 详解1 JVM概述2 JVM体系结构2.1 类加载器2.2 运行时数据区2.3 执行引擎3 JMM Java内存模型4 GC(Garbage Collection,垃圾回收)4.1 GC判断策略4.2 GC收集算法4.3 HotSpot GC 收集器5 JVM 调优5.1 常见参数5.2 调优目标5.3 调优步骤5.3 调优步骤 JVM 详解 1 JVM概述 JVM(Java Virtual Machine, Java虚拟机),是一种用于计算设备的规范,通过仿真模拟各种计算机功能来实现。
[JVM]阿里的jvm分析工具arthas
新一的技术笔记
08-11 3359
前言 jvm分析工具有很多,但是我还是用jmap jstack 和arthas。 阿里的东西确实不错~ 要整的东西有好多,接下来看G1的回收算法。 arthas怎么读?[ 'ɑ: θəs ] 阿瑟斯 使用 https://arthas.aliyun.com/doc/quick-start.html 可以用这个快速入门; 下载: curl -O https://arthas.aliyun.com/arthas-boot.jar 启动arthas java -jar ar..
JVM原理详解
12-20
1,通俗讲解JVM运行原理,各组成部分的作用,包括栈、堆等2,使用visio视图,直观介绍JVM组成3,介绍线程安全产生的原因4,面试题中存在的些许JVM题目讲解
java内存查看与分析
樵夫后院
08-07 973
      业界有很多强大的java profile的工具,比如Jporfiler,yourkit,这些收费的东西我就不想说了,想说的是,其实java自己就提供了很多内存监控的小工具,下面列举的工具只是一小部分,仔细研究下jdk的工具,还是蛮有意思的呢:)     1:gc日志输出        在jvm启动参数中加入 -XX:+PrintGC -XX:...
jvm(四)——JVM自带内存分析工具详解
热门推荐
节至
09-09 4万+
在进行java程序问题定位时,内存问题定位是很关键的一招。jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole、大名鼎鼎的VisualVM,IBM的Memory Analyzer等等,但是在生产环境出现问题的时候,工具的使用会有所限制。所有的工具几乎都是依赖于jdk的接口和底层的这些命令,研究和掌握这些命令的使用也让我们更...
详细介绍jvm内存模型
05-05
Java虚拟机(JVM)内存模型是JVM用于管理Java程序运行时内存的一种机制。JVM将内存划分为不同的区域,每个区域都有自己的用途和生命周期。这些区域包括: 1. 程序计数器(Program Counter Register):程序计数器是一块较小的内存区域,它用于记录当前线程所执行的字节码指令的地址。每个线程都有一个独立的程序计数器。 2. Java虚拟机栈(Java Virtual Machine Stacks):Java虚拟机栈是线程私有的,它用于存储Java方法执行时的局部变量、操作数栈、动态链接、方法出口等信息。 3. 本地方法栈(Native Method Stack):本地方法栈与Java虚拟机栈类似,但是它是为本地方法服务的。 4. Java堆(Java Heap):Java堆是Java虚拟机管理的内存中最大的一块。Java对象实例和数组都在堆上分配内存。堆是所有线程共享的一块内存区域。 5. 方法区(Method Area):方法区是用于存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 6. 运行时常量池(Runtime Constant Pool):运行时常量池是方法区的一部分,用于存放编译器生成的字面量和符号引用。 7. 直接内存(Direct Memory):直接内存不是JVM运行时数据区的一部分,但是它也可以被JVM所管理。在使用NIO(New IO)时,可以使用直接内存来提高IO性能。 以上就是JVM内存模型的主要区域。JVM内存模型的划分对于Java程序的运行和调优都非常重要。在实际开发中,需要根据具体情况调整JVM内存的配置,以达到更好的性能表现。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • C语言文件操作(含详细步骤) 51722
  • 刨析TCP/IP五层模型(超详细) 8510
  • 探讨getchar与scanf的区别 8504
  • 线程1(Thread) 4640
  • 哈希表查找——等概率情况下查找成功和查找不成功的平均查找长度的计算 4559

分类专栏

  • JavaEE 4篇
  • JavaSE 11篇
  • 软件测试 8篇
  • JavaWeb 17篇
  • MySQL 4篇
  • LeetCode 3篇
  • 算法 14篇
  • c语言 19篇
  • 数据结构 17篇
  • 智力题 4篇

最新评论

  • 探讨getchar与scanf的区别

    drive_wajueji: 鹏哥弟子

  • 求0-10000之间的水仙花数,并将这个数输出,打印。

    凌辰——宁: 感觉还是有点问题呀,2就不符合吧

  • 使用mybatis实现CRUD(超详细)

    Zainyu1234: 这真的是一篇很好的文章,果断收藏了!!!

  • maven的使用

    Starry Sky001: 简明扼要

  • maven的使用

    hjycycyc: 这是我看过最好的教程了,真的比视频讲解还清楚,而且还省时间

最新文章

  • ReentranLock超详细讲解
  • SpringBootApplication最详细注解
  • HashMap最全面试题
2023年2篇
2022年47篇
2021年38篇

目录

目录

评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zjruiiiiii

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

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

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

打赏作者

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

抵扣说明:

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

余额充值

深圳SEO优化公司横岗阿里店铺运营宝安品牌网站设计吉祥模板制作石岩建网站丹竹头网站seo优化大鹏至尊标王坪山网页制作广州模板网站建设丹竹头SEO按天扣费宝安SEO按天计费坂田百度seo盐田设计公司网站大鹏网站优化按天扣费福永网站优化推广大浪网站搜索优化吉祥网站优化按天计费丹竹头SEO按效果付费塘坑外贸网站建设惠州如何制作网站永湖网站制作设计平湖网站搭建同乐优化西乡网络广告推广福田模板制作南联百搜标王南联阿里店铺运营同乐建网站福田设计公司网站龙华关键词按天扣费沙井百姓网标王歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化