当前位置: 首页 > news >正文

JVM学习

JVM的理解以及java8的了解

JVM简介:
java虚拟机本质是就是一个程序, 通过类加载器加载java文件到数据区,然后用引擎与操作系统进行交互
797576-20190814180121284-1711067511.png

运行在操作系统之上,与硬件没有直接交互
797576-20190812132917126-1704008797.png

加载java文件

JVM classloader类加载器的(继承关系)
  • 1.启动类加载器(bootstrap--c++)
    虚拟机自带的加载器(路径jre/lib/rt.jar),加载java自带的class文件,java依赖库(jre中),获取加载器返回对象null
  • 2.扩展类加载器(Extension--java)
    加载第三方依赖类(第三方jar包)获取加载器为:ExtClassLoader
  • 3.应用程序类加载器(App--java):也叫系统类加载器,加载当前应用的classpath的所有类
    AppClassloader 自定义类当前的加载器
  • 4.自定义加载类(自己编写继承实现类 Java.lang.ClassLoader)

连接操作系统

执行引擎Execution Engine
native interface

java本身不能对操作系统底层进行访问和操作 但是可以通过JNI接口调用其他语音来实现对底层的调用

核心块

Native Method Stack

native栈,存放native方法

PC寄存器

每一个线程都有一个程序计数器,是线程私有的,就是一个指针,只想方法区中的方法字节码(用来存储指向下一条指令的地址,也即将执行的代码),有执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略

  • 1、也叫栈内存,主管java程序的运行,线程创建时创建,它的生命周期跟随线程的生命周期;线程结束,栈内存就释放, $\color{red}{red}$ $\color{blue}{对于栈来说不存在垃圾回收问题},只要线程一结束,栈就over,生命周期和线程一致,是线程私有的
    基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配
  • 2、java.lang.StackOverflowError
    一致调用栈中的方法,死循环递归调用;导致java.lang.StackOverflowError
方法区

方法去是线程共享的,通常用来保存装在的类的原结构信息

堆(Heap)

堆内存逻辑上分为三个区:
797576-20190813175902816-1822005054.png

  • 1.新生区
    - a.伊甸区
    new 的对象存放在伊甸园区,
    - b.幸存0区
    - c.幸存1区
    默认幸存15次之后去养老区
  • 2.养老区
  • 3.永久存储区(非堆内存)java不在有永久带,取而代之的是【元空间】
    堆内调优
    XX|名称|介绍
    -|-|-
    -Xms|堆内存的初始大小|设置初始分配大小,默认为物理内存的“1/64”
    -Xmx|堆内存的最大设置|最大分配内存,默认为屋里内存的“1/4”
垃圾回收(GC)
  • Minor(次要的) GC 轻量级的垃圾回收
    YGC :对新生代堆进行gc。频率比较高,edn区空间不足时执行young GC

  • Major(重大的) GC
    FGC :old区空间不足时,perm空间不足,调用system.gc(), ygc的悲观策略都会执行FGC

Java 8 不再有永久带,取而代之的是元空间(Metaspace)

堆内存溢出,GC回收的速率小于垃圾产生的速率;以至于垃圾的大小大于jvm设置的最大内存

java.lang.OutOfMemoryError:
String str = "www.baidu.com";
        while (true){
            str = str + new Random().nextInt(12122) + new Random().nextInt(99999999);

       }

MAT eclipse Memory Analyzer

内存快照文件抓取与分析

分析dump文件,快速定位内存泄漏问题

-Xms1m -Xmx8m -XX:+heapDumpOutOfMemoryError 生成内存快照文件(MAT分析)

javap jmap jstack jinfo jqs jshell

说明

类加载器机制:双亲委派机制 + 沙箱机制:防止恶意代码对java代码的破坏,表现:不能自己编写原有的类,如自定义String类

什么是OOM,写代码实现Stack Overflow和OutOfMemoryError

JVM常用的调优

内存快照抓取和MAT分析hprof文件

idea 内存快照抓取hprof文件

-XX:+heapDumpOutOfMemoryError -XX:HeapDumpPath=D:\dump\gc.hprof

常见的OOM以及解决办法

  • 1、OOM for Heap=>例如:Java.lang.OutOfMemoryError: Java heap space

【分析】
此OOM是由于JVM中heap的最大值不满足需要,将设置heap的最大值调高即可,参数样例为:-Xmx2G
【解决方法】
调高heap的最大值,即-Xmx的值调大。

  • 2、OOM for Perm=>例如:java.lang.OutOfMemoryError: Java perm space
    【分析】
    此OOM是由于JVM中perm的最大值不满足需要,将设置perm的最大值调高即可,参数样例为:-XX:MaxPermSize=512M
    【解决方法】
    调高heap的最大值,即-XX:MaxPermSize的值调大。
    另外,注意一点,Perm一般是在JVM启动时加载类进来,如果是JVM运行较长一段时间而不是刚启动后溢出的话,
    很有可能是由于运行时有类被动态加载进来,此时建议用CMS策略中的类卸载配置。
    如:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled
  • 3、OOM for GC=>例如:java.lang.OutOfMemoryError: GC overhead limit exceeded
    【分析】
    此OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略,在一定比例下开始GC而不要使用默认的策略,或者将新代和老代设置合适的大小,
    需要进行微调存活率。
    【解决方法】
    改变GC策略,在老代80%时就是开始GC,并且将-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)设置的更合理。
  • 4、OOM for native thread created=>例如:java.lang.OutOfMemoryError: unable to create new native thread
    【分析】
    参考如下:
    (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
    MaxProcessMemory 指的是一个进程的最大内存
    JVMMemory JVM内存
    ReservedOsMemory 保留的操作系统内存
    ThreadStackSize 线程栈的大小
    如果JVM内存调的过大或者可利用率小于20%,可以建议将heap及perm的最大值下调,并将线程栈调小,即-Xss调小,如:-Xss128k
    【解决方法】
    在JVM内存不能调小的前提下,将-Xss设置较小,如:-Xss:128k
  • 5、OOM for allocate huge array=>例如:Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit

    分析】
    此类信息表明应用程序(或者被应用程序调用的APIs)试图分配一个大于堆大小的数组。例如,如果应用程序new一个数组对象,大小为512M,但是最大堆大小为256M,因此OutOfMemoryError会抛出,因为数组的大小超过虚拟机的限制。
    解决方法】
    (1)、首先检查heap的-Xmx是不是设置的过小
    (2)、如果heap的-Xmx已经足够大,那么请检查应用程序是不是存在bug,例如:应用程序可能在计算数组的大小时,存在算法错误,导致数组的size很大,从而导致巨大的数组被分配。

  • 6、 OOM for small swap=>例如:Exception in thread "main": java.lang.OutOfMemoryError: request bytes for . Out of swap space?

    【分析】
    抛出这类错误,是由于从native堆中分配内存失败,并且堆内存可能接近耗尽。这类错误可能跟应用程序没有关系,例如下面两种原因也会导致错误的发生:
    (1)操作系统配置了较小的交换区
    (2)系统的另外一个进程正在消耗所有的内存
    【解决方法】
    (1)、检查os的swap是不是没有设置或者设置的过小
    (2)、检查是否有其他进程在消耗大量的内存,从而导致当前的JVM内存不够分配。

注意:虽然有时部分显示导致OOM的原因,但大多数情况下,显示的是提示分配失败的源模块的名称,所以有必要查看日志文件,如crash时的hs文件。

转载于:https://www.cnblogs.com/monkay/p/11339350.html

相关文章:

  • Linux清除痕迹
  • luogu2015 二叉苹果树
  • Docker安装LogonTracer
  • 代码安全审计工具
  • spring中bean配置和bean注入
  • Windows下同时安装python2和python3如何兼容版本
  • 极客时间-左耳听风-程序员攻略-技术资源集散地
  • 处理提交html危险代码的异常方法
  • JUC 总结
  • 信息收集-DNS记录查询
  • JSON Hijacking漏洞
  • Failure [DELETE_FAILED_INTERNAL_ERROR]之后rm apk卸载
  • 浏览器中的文件传输过程
  • 面试常考 大数加减乘除
  • Hibernate一级缓存Session和对象的状态
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • CentOS6 编译安装 redis-3.2.3
  • Cookie 在前端中的实践
  • Go 语言编译器的 //go: 详解
  • Invalidate和postInvalidate的区别
  • js对象的深浅拷贝
  • LintCode 31. partitionArray 数组划分
  • React的组件模式
  • supervisor 永不挂掉的进程 安装以及使用
  • 笨办法学C 练习34:动态数组
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 通过npm或yarn自动生成vue组件
  • 详解NodeJs流之一
  • 小程序开发之路(一)
  • 智能网联汽车信息安全
  • Nginx实现动静分离
  • 交换综合实验一
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • (02)Hive SQL编译成MapReduce任务的过程
  • (C#)获取字符编码的类
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (学习日记)2024.02.29:UCOSIII第二节
  • (转)ABI是什么
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)四层和七层负载均衡的区别
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .net core控制台应用程序初识
  • .NET Micro Framework初体验
  • .NET 反射的使用
  • .NET 事件模型教程(二)
  • .skip() 和 .only() 的使用
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @RequestMapping用法详解
  • @test注解_Spring 自定义注解你了解过吗?
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [acwing周赛复盘] 第 69 场周赛20220917
  • [AIGC] 如何建立和优化你的工作流?
  • [AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)