当前位置:首页 > Java技术 > JVM快速入门

JVM快速入门

2022年08月04日 19:07:09Java技术2

JVM快速入门 _ JavaClub全栈架构师技术笔记

1、JVM探究?

几道面试题:

1、请你谈谈对jvm的理解?java8的虚拟机和之前的变化更新?
2、什么是oom?什么是栈溢出(StackOverflow) ?怎么分析?
3、jvm常见的调优参数有哪些?
4、内存快照如何抓取,怎么分析Dump文件?
5、谈谈jvm中,类加载器你的认识?

可以在cmd中输入java -version ,查看自己虚拟机的版本
JVM快速入门 _ JavaClub全栈架构师技术笔记

2、JVM的位置?

JVM快速入门 _ JavaClub全栈架构师技术笔记

3、JVM的体系结构?

JVM的调优是针对于方法区和堆 ;而大部分的调优针对于
JVM快速入门 _ JavaClub全栈架构师技术笔记
JVM架构图
JVM快速入门 _ JavaClub全栈架构师技术笔记

4、类加载器

作用:类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。

package com.gd.Jvm;

public class Car {
     
    //类是模板,对象是具体的
    //进入JVM之后,先进入类加载器ClassLoader-> 然后初始化,得到Car类的Class对象
    public static void main(String[] args) {
     
        Car car1=new Car();
        Car car2=new Car();
        Car car3=new Car();
        System.out.println(car1.hashCode());
        System.out.println(car2.hashCode());
        System.out.println(car3.hashCode());
		//不同的对象,对应的Class类对象是一致的
        Class<? extends Car> aClass1 = car1.getClass();
        Class<? extends Car> aClass2 = car2.getClass();
        Class<? extends Car> aClass3 = car3.getClass();
        System.out.println(aClass1.hashCode());
        System.out.println(aClass2.hashCode());
        System.out.println(aClass3.hashCode());
    }

}

JVM快速入门 _ JavaClub全栈架构师技术笔记
类加载器:

  • 虚拟机自带的加载器
  • 启动类加载器(根加载器)
  • 扩展类加载器
  • 应用程序加载器(系统类加载器)

        ClassLoader classLoader = aClass1.getClassLoader();
        System.out.println(classLoader); //sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println(classLoader.getParent());//sun.misc.Launcher$ExtClassLoader@1540e19d   在jdk/jre/lib/ext 中
        System.out.println(classLoader.getParent().getParent());//null   (1)不存在 (2)java程序获取不到

应用程序加载器获取到的位于rt.jar 包下的java.lang 包下的ClassLoader 类
JVM快速入门 _ JavaClub全栈架构师技术笔记
扩展加载器位于在jdk/jre/lib/ext 中
JVM快速入门 _ JavaClub全栈架构师技术笔记

5、双亲委派机制

创建一个java.lang包,创建String类
重写toString方法,调用toString方法,出现异常
App -> Exc -> BooT(最终执行)
如果向上找,没找到对应的加载器,又会向下走,回到应用程序加载器

package java.lang;

public class String {
     
    /*
    双亲委派机制:安全
    App ->  Exc  ->  BooT(最终执行)
    1、App 应用程序加载器(AppClassLoader)
    2、Exc 扩展类加载器(ExtensionClassLoader)
    3、BOOT 启动类加载器(BootstrapClassLoader)
     */
    @Override
    public String toString() {
     
        return "toString";
    }

    public static void main(String[] args) {
     
        String string =new String();
        String s = string.toString();
        System.out.println(s);
        System.out.println(s.getClass().getClassLoader());

    }

}

JVM快速入门 _ JavaClub全栈架构师技术笔记
eg:再次创建一个包,创建一个类,类名定义为Student ,不与java定义的类重名

package com.gd.Jvm;

public class Student {
     
    @Override
    public String toString() {
     
        return "studentString";
    }

    public static void main(String[] args) {
     
        Student student =new Student();
        String s = student.toString();
        System.out.println(s); //studentString
        System.out.println(s.getClass().getClassLoader());//null
        new  Thread().start();
    }
    /*
    1、类加载器收到类加载的请求,Application
    2、将这个请求向上委托给父类加载器去完成,一直向上委托,知道启动类加载器
    3、启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前加载器,否则,抛出异常,通知子加载器进行加载
    4、重复步骤三
    Class Not Found
    null :JAVA 调用不到~ c ,c++
    Java = C++ :去掉繁琐的东西,指针,内容管理~
    */
}

JVM快速入门 _ JavaClub全栈架构师技术笔记
线程类调用start方法,线程级别的java无法处理,就调用本地方法start()
JVM快速入门 _ JavaClub全栈架构师技术笔记

6、沙箱安全机制

作用:防止恶意代码污染java源代码
守护了被信任的类库边界
将代码归入保护域,确定了代码可以进行哪些操作

比如我们定义了一个类名为String所在的包名为Java.lang,因为这个类本来属于jdk的,如果没有沙箱安全机制,这个类将会污染到系统中的String ,但是由于沙箱安全机制,所以就委托顶层的引导类加载器查找这个类,如果没有的话就委托给扩展类加载器,再没有就委托到系统类加载器。但是由于String就是jdk源代码,所以在引导类加载器那里就加载到了,先找到先使用,所以就使用引导类加载器里面的String ,后面的一概不能使用,这就保证了不被恶意代码污染。

package com.gd.Jvm;

public class Demo {
     
    public static void main(String[] args) {
     
        Demo demo =new Demo();
        demo.test1();
    }
    public void test1(){
     
        test2();
    }
    public  void test2(){
     
        test1();
    }
}

栈溢出
JVM快速入门 _ JavaClub全栈架构师技术笔记

7、Native

1、会进入本地方法栈,调用本地方法接口 JNI
2、JNI作用:扩展Java的使用,融合不同的编程语言为java所用,最初为C 、 C++
Java诞生的时候,C 、C++ 横行,想要立足,必须要有调用 C 、C++的程序,它在内存区域中专门开辟了一块标记区域:Native Method Stack 用来登记native方法
3、在最终执行的时候,加载本地方法库中的方法通过JNI
4、Java程序驱动打印机,管理系统,目前该方法使用的越来越少了,在企业级应用已经比较少见。
5、现在的异构领域间通信很发达,调用其他接口:socket 、 http…

package com.gd.Jvm;

public class Demo1 {
     
    public static void main(String[] args) {
     
        new Thread(()->{
     

        },"hello").start();
    }

    private native void start0();
}

凡是带了native关键字的,说明java的作用范围达不到了, 回去调用底层c语言的库
JVM快速入门 _ JavaClub全栈架构师技术笔记

8、PC寄存器(Program Counter Register)

每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向一条指令的地址,也指向要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计
pc寄存机是jvm中唯一一个不会栈溢出的

9、方法区(Method Area)

方法区:static .final.Class .常量池… 运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关
方法区是所有线程共享的,所有字段和方法字节码,以及一些特殊方法
如:构造方法、接口代码;所有定义的方法的信息都保存在该区域,此区域属于共享空间。


public class Test {
     
    private  int a;
    private String name="jvmstudy";

    public static void main(String[] args) {
     
        Test test =new Test();
    }
}

JVM快速入门 _ JavaClub全栈架构师技术笔记

10、栈(Stack)

1、栈是一种数据结构(后进先出),队列是先进先出的数据结构
2、为什么main方法是最先被执行的,但是最后结束?
main方法最先被压入栈,最后出栈
JVM快速入门 _ JavaClub全栈架构师技术笔记
3、栈的别名:栈内存;主要管理程序的运行;生命周期与线程同步,线程结束,栈内存即被释放,
不存在垃圾回收的问题
4、栈里面存放的就是8大基本数据类型以及对象的引用以及实例方法
5、栈帧:是一片一片的…;压入一个方法入栈,就是栈帧
stack2:;先进来被调用
正在执行的方法,是位于栈顶的
JVM快速入门 _ JavaClub全栈架构师技术笔记

栈、堆、方法区 关系

JVM快速入门 _ JavaClub全栈架构师技术笔记

11、三种JVM

我们普遍使用的是sun公司提供的HotSpot
JVM快速入门 _ JavaClub全栈架构师技术笔记
BEA
IBM的J9VM

12、堆(Heap)

一个JVM只有一个堆内存,堆内存的大小是可以调节的

Car car =new Car();
Class<? extends Car> aClass =car.getClass();
//类加载器
ClassLoader classloader = aClass.getClassLoader(); 

类加载器读取了类文件后,将类,方法,常量 引用类的真实对象,存入堆中,堆划分为新生区,老年区,永久区
在新生区中进行垃圾回收,轻GC,经过伊甸园区随后进入到幸存0区,然后到幸存1区。
如果新生区满了,则进入老年区,重GC
如果老年区满了,则进入永久存储区
最终,内存满了,就会出现OOM,出现堆内存溢出的错误

  • eg:永久循环,造成了OOM的错误
    JVM快速入门 _ JavaClub全栈架构师技术笔记
package com.ffyc.database.jvm.heap;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Demo1 {
     
    public static void main(String[] args) {
     
        List<Integer> list = new ArrayList();
        while(true){
     
            list.add(new Random().nextInt());
        }
    }
}

JVM快速入门 _ JavaClub全栈架构师技术笔记
JVM快速入门 _ JavaClub全栈架构师技术笔记

13、新生区、老年区、永久区

JVM快速入门 _ JavaClub全栈架构师技术笔记JVM快速入门 _ JavaClub全栈架构师技术笔记
注意:一般对象都是临时变量
永久代:存放class对象,变量等,不存在垃圾回收
在jdk1.8之后,永久存储区更改为元空间:逻辑存在,物理不存在
方法区里面为常量池
程序OOM了,该怎么办?:
(1)扩大堆内存,看结果
(2)分析内存,看那个地方出现了问题(专业工具)

1、在一个项目中,突然出现了OOM故障,那么该如何排除故障,研究为什么会出错?
(1)能够看到代码第几行出错,内存快照分析工具:MAT,JProfiler
(2)Debug,一行一行的分析
MAT,JProfiler的作用:
分析Dump内存文件,
快速定位内存泄漏
2、使用JProfiler工具分析OOM原因?
(1)在idea中安装插件
…以后更新

14、堆内存调优

eg:JVM快速入门 _ JavaClub全栈架构师技术笔记
默认: 分配的总内存是电脑内存的1/4 ; 初始化的内存 是电脑内存的1/64;
JVM快速入门 _ JavaClub全栈架构师技术笔记

调整-Xms527m -Xmx527m -XX:+PrintGCDetails

JVM快速入门 _ JavaClub全栈架构师技术笔记
调小看看
-Xms1m -Xmx1m -XX:+PrintGCDetails
JVM快速入门 _ JavaClub全栈架构师技术笔记

15、GC

内存效率:复制算法>标记清除>标记压缩(时间复杂度)
内存整齐度:复制算法=标记压缩>标记清除
内存利用率:标记压缩=标记清除>复制算法

GC题目:
1、JVM的内存模型和分区模型,详细到每个区放什么?
2、堆里面的分区有哪些?Eden ,from,to ,老年区 ,说说各有什么特点?
3、GC的算法有哪些?
标记清除法、标记整理、复制算法、引用计数器
4、轻GC和重GC分别在什么时候发生?

引用计数器

首先给每个对象都分配一个引用计数器:计数器本身也会有消耗
JVM快速入门 _ JavaClub全栈架构师技术笔记

(1)复制算法

from->to 谁空谁是to
每次GC:都会将Eden(伊甸园区) 活的对象移到幸存区,一旦Eden区被GC后,就会是空的!
好处:没有内存碎片
坏处:浪费了内存空间:多了一半空间永远是to,假设对象100%存活【极端情况】(比较危险)
最佳使用场景:对象存活度较低的时候:新生区用复制算法
JVM快速入门 _ JavaClub全栈架构师技术笔记

(2)标记清除算法

(1)扫描这些对象,对活着的对象进行标记
(2)清除:对没有标记的对象,进行清除
优点:不需要额外的空间!
缺点:两次扫描,严重浪费时间,会产生内存碎片
JVM快速入门 _ JavaClub全栈架构师技术笔记

(3)压缩清除算法

防止内存碎片产生,再次扫描,向一端移动存活的对象多了一个移动成本

  • 难道没有最优算法吗?
  • 没有,只有最合适的算法 - -> GC:分代收集算法
    年轻代:存活率低,复制算法
    老年代:区域大,存活率高;标记清除+标记压缩混合实现
    JVM快速入门 _ JavaClub全栈架构师技术笔记

16、JMM

1、什么是JMM?
Java Memory Model(Java内存模型), 围绕着在并发过程中如何处理可见性、原子性、有序性这三个特性而建立的模型。
2、干嘛的?
作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到这个规则)
JMM规定了所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存(Working Memory),线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成
3、他该如何学习?
从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。本地内存它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化之后的一个数据存放位置
JVM快速入门 _ JavaClub全栈架构师技术笔记

作者:高朵
来源链接:https://blog.csdn.net/qq_48019875/article/details/121373060

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/17406.html

分享给朋友:

“JVM快速入门” 的相关文章

性能优化|快速掌握JVM内存分配机制

性能优化|快速掌握JVM内存分配机制

JVM整体结构 堆 线程共享的区域,也是垃圾回收器要收集的区域,这地方主要保存用户创建的对象。例如 new User(),这个对象是保存在堆上面的。...

OpenWrite技术自媒体界的JVM一次编辑、随处发布

OpenWrite技术自媒体界的JVM一次编辑、随处发布

原文 :https://mp.weixin.qq.com/s/KUtJ2dwhBRuJ2G_-PkQFEA 最懂你的科技自媒体管理平台 【实用小工具推荐】给科技或技术同学们推荐一款比较好用的工具,可以实现一稿多发,主流的技术渠道基本涵...

Java String(JVM角度)

Java String(JVM角度)

基本特性 存储结构变更 jdk8及之前的jdk版本中,String的内存存储结构是char[]字符数组,但是在Jdk9及之后改成了byte[]字节数组。 原因是,堆空间中大部分的字符串内容都是latin字符,基本上...

JVM 从入门到精通(二)JVM和Java体系结构

JVM 从入门到精通(二)JVM和Java体系结构

写在前面:我是「云祁」,一枚热爱技术、会写诗的大数据开发猿。昵称来源于王安石诗中一句 [ 云之祁祁,或雨于渊 ] ,甚是喜欢。 写博客一方面是对自己学习的一点点总结及记录,另一方面则是希望能够帮助更多对大数据感兴趣的朋友。如果你也对 数据中台...

JVM中有哪些垃圾收集器?

写在前面 本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 新生代垃圾...

JVM学习1--数字存储,内存模型,指令重排

JVM学习1--数字存储,内存模型,指令重排

一、数字在计算机中的存储   整数:以补码形式存储。     补码:正数的补码是自身,负数的补码是取反码加1(取反码时符号位还是1)   浮点型:以float类型表示            注意一下,这八位指数实际上是(127...

浅谈JVM内存模型

浅谈JVM内存模型

JAVA虚拟机在执行JAVA程序的时候,会把它管理的内存分成若干不同的数据区域,每个区域都有各自的用途。目前大致把JVM内存模型划分为五个区域:程序计数器,虚拟机栈,本地方法栈,堆和方法区。   程序计数器 程序计数器(ProgramCounterR...

深入理解JVM(1)——JVM内存模型

Java虚拟机的内存空间分为五个部分,分别是: 程序计数器; Java虚拟机栈 本地方法栈 堆 方法区 接下来对这五部分分别进行详细的介绍 1、程序计数器:   a)什么是程序计数器:程序计数器是内存中的一个很小...

JVM - 双亲委派

JVM - 双亲委派

# JVM - 双亲委派 JDK版本:1.8 # 1、双亲委派机制 Java虚拟机对于class文件采用的加载策略是按需加载。也就是当需要使用该类时才会将该类的.class文件加载到内存中生成Class对象。并且加载某...

深入理解JVM—JVM内存模型

深入理解JVM—JVM内存模型

原文地址:http://yhjhappy234.blog.163.com/blog/static/316328322011101723933875/?suggestedreading&wumii 我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。