认识jvm(一)

jvm内存区域与溢出

为什么学习jvm

  • 木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时候,那么就需要你对jvm的了解掌握。
  • 当一个系统出现内存溢出,内存泄露的时候,因为你懂jvm知识,可以更加快速定位错误,可以通过参数去合理设置各内存区域的内存容量。
  • 因为你对jvm的认识,写代码的时候会潜意识地让你注意代码质量,可能你会说是那是小小的性能提升,但是量变会导致质变的。

jvm内存区域

jvm内存划分

  • 方法区
  • 虚拟机栈
  • 本地方法栈
  • 程序计数器

程序计数器

  • 当前线程所执行的字节码的行号指示器。
  • 因为cpu的每个核心只能同时运行一个线程,所以当一个线程执行完时间片后切换到另一个线程,切换时为了能恢复到正确的执行位置,所以需要程序计数器(学过计算机组成原理的应该比较熟悉)。
  • 如果是线程执行的是一个java方法那么此时计数器记录的是正在执行的虚拟机字节码指令的地址。如果是nativ方法(非java代码),计数器值为空。

虚拟机栈

  • java执行的内存模型,栈由栈帧组成,线程调用一个java方法时,创建一个栈帧,方法返回时,栈帧弹出。栈帧入栈出栈的过程就是方法开始结束的过程
  • 栈帧存储局部变量区(存放基本数据类型数据,对象指针),操作数栈(存放操作数,比如加法运算的时候操作数栈取值,计算后再压入栈),动态链接,方法出口。

本地方法栈

  • 和虚拟机栈作用类似,只不过服务对象不同,本地方法服务对象是非java方法,虚拟机栈服务对象是java方法

方法区

  • 存放类的信息、常量、静态变量等
  • 运行时常量池是方法区一部分,主要存放字面量(如final修饰的变量)和符号引用量(编译原理方面)

  • 存放对象,对象要在堆上分配内存
  • 堆分为年轻代和年老代
  • 年轻代分为伊甸区(Eden space)和幸存者区(Survivor space)
  • 幸存区分为from和to空间

总结

  • jvm的内存区域划分为程序计数器,虚拟机栈,本地方法栈,方法区,堆。
  • 程序计数器,虚拟机栈和本地方法栈都是线程独享的,而方法区和堆是线程共享的

溢出

理清概念

  • 操作系统分配给进程的内存是有限的,而jvm的内存区域我们已经知道,当我们设置好堆和方法区的最大容量后,那么剩下的内存将分配给虚拟机栈和本地方法区和程序计数器(占用内存少)。
  • 两种常见的溢出异常,一种OutOfMemoryError(OOM),一种StackOverflowError。

各区溢出情况

  • 堆溢出,当我们创建的对象占用的内存超过最大堆容量时候,会抛出OOM
  • 本地方法栈和虚拟机栈溢出:当请求的栈深度超过虚拟机所允许的深度的时候会抛出栈溢出,这种情况我们在使用递归出错的时候经常遇到;还有就是出现OOM的情况,我们知道分配给这两个栈的内存是有限,和线程数和线程的栈内存有关系,那么当我们其中任意一个过大的话,都有可能造成OOM
  • 方法区和运行时常量池溢出:方法区存放类的信息,有时我们用的框架在动态代理的时候会动态生成CLASS,这个时候有可能会出现方法区的OOM;而常量池溢出我们可以用String的intern方法(如果常量池没有与字符串相等的字符串,就将这个字符串存入方法区)进行模拟。

设置各区的jvm参数

  • 设置堆的最小值-Xms,堆的最大值-Xmx
  • 设置永久代(jdk8之前用永久代来实现方法区)的最小值-XX:PermSize ,最大值-XX:MaxPermSize
  • 设置栈容量-Xss

延伸

关于创建字符串

        String s2=new String("jiajun");
        String s6=new String("jiajun");
        System.out.println(s2==s6);
  • 结果为false,都存放在堆内存,但是两个地方。
        String s6=new String("jiajun");
        String s1="jiajun";
        System.out.println(s1==s6);
  • 结果为false,s6存放在堆当中,而s1存放在常量池当中
        String s1="jiajun";
        String s7="jiajun";
        System.out.println(s1==s7);
  • 结果为true,都是存放在常量池
        String s4="jia";
        String s5=s4+"jun";
        String s1="jiajun";

        System.out.println(s1==s5);
  • 结果为false,变量的值在运行的时候才确定,所以此时s5实际上是new一个对象
        String s3="jia"+"jun";
        String s1="jiajun";
        System.out.println(s1==s3);
  • 结果为true,此时s1 s3都是指向常量池一个string
        String s1="jiajun";
        String s8=new String("jia")+"jun";
        System.out.println(s1==s8);
  • 结果为false,此时s8同样是new出来一个对象

我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

时间: 2024-10-11 14:41:25

认识jvm(一)的相关文章

JVM原理讲解和调优

一.什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的. Java语言的一个非常重要的特点就是与平台的无关性.而使用Java虚拟机是实现这一特点的关键.一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码.而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译.Java语言使用Java虚拟机屏蔽了与具体平台相关的信息

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Java性能优化之JVM GC(垃圾回收机制)

Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行.当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成.GC优化很多时候就是减少stop-the-world 的发生. JVM GC回收哪个区域内的垃圾? 需要注意的是,JV

JVM垃圾回收算法

1.堆的分代和区域 (年轻代)Young Generation(eden.s0.s1  space)    Minor GC (老年代)Old Generation (Tenured space)     Major GC|| Full GC (永久代)Permanent Generation (Permanent  space)[方法区(method area)]    Major GC 本地化的String从JDK 7开始就被移除了永久代(Permanent Generation ) JDK

Java 详解 JVM 工作原理和流程

作为一名Java使用者,掌握JVM的体系结构也是必须的.说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java编程语言.Java类文件格式.Java虚拟机和Java应用程序接口(JavaAPI).它们的关系如下图所示: 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执

JVM 什么时候会full gc

除直接调用System.gc外,触发Full GC执行的情况有如下四种.1. 旧生代空间不足旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:java.lang.OutOfMemoryError: Java heap space 为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收.让对象在新生代多存活一段时间及不要创建过大的对象及数组.2. Permanet Generation空间

jvm java内存区域的介绍

jvm虚拟机在运行时需要用到的内存区域.广泛一点就是堆和栈,其实不然,堆和栈只是相对比较笼统的说法,真正区分有如下几个 先上图一: 总的就是 java的内存模型 内存模型又分堆内存(heap)和方法区(有时也称为non-heap)和栈 堆又分新生代(Young)和老年代(old/Tenured) 新生代又分默认比例为8:1:1的eden空间.from survivor空间.to survivor空间 当进行垃圾回收时,eden.survivor from 存活得对象会复制到servivor to

JVM Safepoint 安全点

一.什么是安全点: 在可达性分析算法中查找存活的对象,首先要找到哪些是GC Roots: 有两种查找GC Roots的方法: 一种是遍历方法区和栈区来查找(保守式GC): 一种是通过OopMap的数据结构来记录引用的位置(准确式GC),如在类加载过程中,JIT编译过程中,分别记录下 类成员 和 调用栈 中的引用的调用信息.对应OopMap的位置即可作用一个安全点.线程只有到达安全点时才能暂停下来进行可达性分析. OopMap:你可以把oopMap简单理解成是调试信息. 在源代码里面每个变量都是有

关于 JDK jre jvm

JDK 全名是 JAVA development kit  是JAVA语言的软件开发工具 包:是整个JAVA开发的核心,没有JDK的话,无法编译Java程序,如果想只运行Java程序,要确保已安装相应的JRE. JDK包含的基本组件包括: javac – 编译器,将源程序转成字节码: jar – 打包工具,将相关的类文件打包成一个文件: javadoc – 文档生成器,从源码注释中提取文档: jdb – debugger,查错工具: java – 运行编译后的java程序(.class后缀的):

JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结--转载http://www.cnblogs.com/kubixuesheng/p/5202561.html

转载自---http://www.cnblogs.com/kubixuesheng/p/5202561.html 俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及到的知识点总结如下: 堆栈是栈 JVM栈和本地方法栈划分 Java中的堆,栈和c/c++中的堆,栈 数据结构层面的堆,栈 os层面的堆,栈 JVM的堆,栈和os如何对应 为啥方法的调用需要栈 属于月经问题了,正好碰上有人问我这类比较基础的知识,无奈我自觉回答不是有效果,现在深入浅出的总结下: 前一篇文章总结了:JV