• jvm学习笔记


    学习视频:https://www.bilibili.com/video/BV1iJ411d7jS?p=4&spm_id_from=pageDriver

    1.JVM的位置

     2.JVM体系结构

     3.双亲委派机制

    A、说明:
    当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
    B、作用:
    1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
    2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
    C、流程图(理解,向上委托,向下加载)

    D、类加载器类别:(由上至下)
    BootstrapClassLoader(启动类加载器)-> ExtClassLoader (标准扩展类加载器)-> AppClassLoader(系统类加载器)-> CustomClassLoader(用户自定义类加载器)

     4.沙箱安全机制

    Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问,那系统资源包括什么?——CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。

    所有的Java程序运行都可以指定沙箱,可以定制安全策略。

     5.native关键字(主要用于方法上)

     1、一个native方法就是一个Java调用非Java代码的接口。一个native方法是指该方法的实现由非Java语言实现,比如用C或C++实现。
    2、在定义一个native方法时,并不提供实现体(比较像定义一个Java Interface),因为其实现体是由非Java语言在外面实现的
    主要是因为JAVA无法对操作系统底层进行操作,但是可以通过JNI(java native interface java本地方法接口)调用其他语言来实现底层的访问。
    举例:Thread类中的start() 方法中调用一个start0()的native方法。

    6.方法区

    1.放了些什么:每个类的结构信息(字段、方法数据、普通方法、构造方法),运行时常量池,静态变量内容。(这是规范,不同虚拟机的实现是不同的 最典型的就是永久代PermGen space和元空间Metaspace)
    实例变量在堆内存中,和方法区无关。
    2.绝对不是用来放方法的
    3.这块区域所有线程共享,存在垃圾回收。

    7.栈

    栈:先进后出,后进先出
    队列:先进先出(FIFO:First input First Output)

    喝多了吐就是栈,吃多了拉就是队列
    为什么main()先执行,最后结束

    每个线程都有自己的栈,栈中的数据都是以栈帧的格式存在;在这个线程上正在执行的每一个方法都各自对应一个栈帧;栈帧是一个内存区块,是一个数据集维系着方法执行过程中的各种数据信息

    栈:8大基本类型+对象引用+实例的方法()

    栈是运行时的单位,Java 虚拟机栈,线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。(方法头开始入栈,结束出栈,方法里面调用别的方法 新的方法就会把旧的压在底下,最上面永远是正在执行的方法,也对应先入后出。)

    局部变量表:存放了编译期可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址)

    8.堆

    Heap,一个jvm只有一个堆内存,堆内存的大小是可以调节的
    类加载器读取了类文件后,一般会把类、方法、常量、变量,保存我们所有引用类型的真实对象。
    (下图为jdk8之前的,jdk8以后永久存储区的名字改为“元空间”)

    永久区:这个区域常驻内存的。用来存放JDK自身携带的class对象,interface元数据,储存的是java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭VM虚拟机就会释放这个区域的内存

    Jdk1.6之前:永久代,常量池在方法区
    Jdk1.7:永久代,慢慢退化,去永久代,常量池在堆中
    Jdk1.8之后:无永久代,常量池在元空间

    什么时候出现永久区满
    一个启动类,加载了大量的第三方jar包,tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满,就会出现OOM

    堆结构

    发生OOM内存溢出,解决方法
    A、 尝试扩大堆内存看结果
    B、 分析内存,看一下哪个地方出现问题(专业工具)

    1、内存溢出:(Out Of Memory—-OOM)
    系统已经不能再分配出你所需要的空间,比如系统现在只有1G的空间,但是你偏偏要2个G空间,这就叫内存溢出
    例子:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那就报错。

    2、内存泄漏: (Memory Leak)
    强引用所指向的对象不会被回收,可能导致内存泄漏,虚拟机宁愿抛出OOM也不会去回收他指向的对象,意思就是你用资源的时候为他开辟了一段空间,当你用完时忘记释放资源了,这时内存还被占用着,一次没关系,但是内存泄漏次数多了就会导致内存溢出

    3、JProfiler工具分析OOM原因:
    分析Dump内存文件,快速定位内存泄漏
    获得堆中的数据
    获得大的对象

     

    -XX:+HeapDumpOnOutOfMemoryError配置jvm参数,获取Heap Dump文件,用于分析结果

    4、jvm调优
    对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。

    JVM性能调优方法和步骤:
    1.监控GC的状态;
    2.生成堆的dump文件;
    3.分析dump文件;
    4.分析结果,判断是否需要优化;
    5.调整GC类型和内存分配;
    6.不断的分析和调整

  • 相关阅读:
    SpringMVC组件解析
    SpringMVC简介
    spring集成web环境
    Spring基于注解的事务控制
    Spring基于XML声明式事务控制
    Spring事务控制&编程式事务控制三大对象
    基于注解的AOP开发
    基于xml的AOP开发
    python字符串操作
    赋值、深拷贝、浅拷贝
  • 原文地址:https://www.cnblogs.com/20183544-wangzhengshuai/p/15230861.html
Copyright © 2020-2023  润新知