java虚拟机概念以及各参数的配置

一.概念

所谓虚拟机,就是一台虚拟的机器。它是一款软件,用来执行一系列虚拟计算机指令,大体上虚拟机可以分为:①系统虚拟机和②程序虚拟机。像Visual Box,VMware就属于系统虚拟机,他们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。程序虚拟机典型代表就是java虚拟机,它专门为执行单个计算机程序而设计,在java虚拟机中执行的指令我们称为java字节码指令。无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中

二.虚拟机的基本结构,基本概念说明

在这里插入图片描述
1.类加载子系统
负责从文件系统或者网络中加载Class信息,记载的信息存放在一块称之为方法区的内存空间。
2.方法区
也叫永久区(Perm),存放一些静态的东西,比如类信息,常量信息,常量池信息,包括字符串字面量和数字常量等,是各个线程共享的内存区域。
3.java堆
在java虚拟机启动的时候建立java堆,它是java程序最主要的内存工作区域。几乎所有的对象实例以及数组都存放到java堆中,堆空间是各个线程共享的内存区域。
4.直接内存
java的NIO库允许java程序使用直接内存,从而提高性能,通常直接内存会优于java堆。读写频繁的场合可能会考虑使用。
5.java栈
每个虚拟机线程都有一个私有的栈,一个线程的java栈在线程创建的时候被创建,java栈中保存着局部变量,方法参数,java的方法调用和返回值以及对象的引用等。
6.本地方法栈
和java栈非常类似,最大不同为本地方法栈用于本地方法调用。java虚拟机允许java直接调用本地方法(通常使用C编写)。
7.垃圾收集器系统
java的核心,也是必不可少的,java有一套自己进行垃圾清理的机制,开发人员无需手动清理。
8.PC(Program Counter)寄存器
也是每个线程私有的空间,java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个java线程总是在执行一个方法,这个方法被称为当前方法,如果当前方法不是本地方法,PC寄存器就会执行当前正在被执行的指令,如果是本地方法,则PC寄存器值为undefined,寄存器存放如当前执行环境指针,程序计数器,操作栈指针,计算的变量指针等信息。
9.执行引擎
虚拟机最核心的组件就是执行引擎了,它负责执行虚拟机的字节码。一般用户先进行编码成机器码后执行。

堆,栈,方法区之间的联系:
首先,堆解决的是数据存储的问题,即数据怎么放,放在哪儿。(存放对象)
栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。(存放局部变量,方法参数以及返回值等)
方法区则是辅助堆栈的永久区(Perm),解决堆栈信息的产生,是先决条件。(存放类信息)
举个例子:
当User类从方法区被实例化出来后,被存储到java堆中,一块内存空间
当我们去使用的时候,都是使用User对象的引用,形如User user = new User();
这里的user就是存放在java栈中的,即User真实对象的一个引用。在这里插入图片描述

三.java堆,java栈以及方法区详解

1.java堆内存空间的划分以及使用情况
java堆是和java应用程序关系最密切的内存空间,几乎所有的对象都会存放在其中,并且java堆完全是自动化管理的,通过垃圾回收机制,垃圾对象会自动清理,不需要显示的释放。
根据垃圾回收机制的不同,java堆有可能拥有不同的结构。最为常见的就是将整个java堆分为新生代和老年代。其中新生代存放新生的对象或者年龄不大的对象,老年带则存放年老的对象。
新生代分为:eden区,s0区,s1区,s0区和s1区也被称为from区和to区,他们是两块大小相等并且可以互换角色的空间。
绝大多数情况下,对象首先分配在eden区,在一次新生代被回收后,如果对象还存活,则会进入s0区或者s1区(要么进入s0区要么进去s1区,一个对象不会既存在s0区又存在于s1区),之后每经过一次新生代回收,如果对象还存活则它的年龄就+1,当对象达到一定的年龄后,则进入老年代。
在这里插入图片描述
2.java栈
java栈是一块县城私有的内存空间,一个栈一般由三个部分组成:局部变量表,操作数栈和帧数据区。
局部变量表:用于存放报错函数的参数以及局部变量
操作数栈:主要保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间
例如:int temp=0,a=1,b=2; temp=a;a=b;b=temp; temp作为中间结果进行两值得交换。计算过程中a,b,temp变量都应该存放在操作数栈内
帧操作区:除了局部变量表和操作数栈以外,栈还需要一些数据来支撑常量池得解析,这里的帧数据区保存着访问常量池的指针,方便程序访问常量池。另外,当函数返回或者出现异常时,虚拟机必须有一个异常处理表,方便发生异常的时候找到异常的代码块,因此异常处理表也是帧数据区的一部分。
3.方法区
java方法区和堆一样,方法区是一块所有线程共享的内存区域,它保存系统的类信息,比如类字段,方法,常量池等。方法区的大小决定了系统可以保存多少各类,如果系统定义太多的类,会导致方法区溢出。虚拟机会抛出OOM内存溢出的错误。

四.虚拟机参数

在虚拟机运行的过程中,如果可以跟踪系统的运行状态,那么对于问题的故障排查会有一定的帮助,为此,虚拟机提供了一些跟踪系统状态的参数,使用给定的参数执行java虚拟机,就可以在系统运行时打印相关日志,用于分析实际问题。我们进行虚拟机参数配置,其实主要就是围绕着堆,栈,方法区进行配置。

1.堆分配参数:
参数分两类,第一类:-XX:+/-格式,对系统(jvm)级别的配置,配置日志信息,和配置jvm使用什么样的垃圾回收器等。符号:"+"表示启用 , "-"表示禁用。
第二类:非-XX格式的,基本上都是对应用层面上的配置。

-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志
-XX:+UseSerialGC 配置串行回收器
-XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况。(年轻带老年带持久带中的区)
-XX:SurvivorRatio=eden/from=eden/to 这个比例为新生代中eden区大小与from区或者to区比例的大小,并不是 与from区和to区和的大小的比例。
-XX:NewRatio 老年代/新生代的比例大小
-XX:+HeapDumpOnOutOfMemoryError使用该参数可以在内存溢出时导出整个堆信息,与之配合使用的还有参数:-XX:HeapDumpPath,可以设置导出堆的路径,下面会举例
-XX:MaxPermSize 对方法区的最大值进行配置,如果过小,系统运行产生大量的类,就会出现永久区内存溢出的问题。初始永久区的参数:-XX:PermSize,使用例子:-XX:PermSize=64M -XX:MaxPermSize=64M

-Xms: 设置java程序启动时初始堆大小
-Xmx: 设置java程序能获得的最大堆大小
-Xmn: 可以设置新生代的大小,设置一个比较大的新生代会较少老年代的大小(因为堆的总大小不会变的),这个参数对系统性能以及GC行为有很大的影响,新生代大小一般会设置整个堆空间的1/4到1/3左右。
-Xss 指定线程的最大栈空间,这个参数也直接决定了函数可调用的最大深度。例:-Xss5m

例:-Xmx20m -Xms5m -XX:+PrintCommandLineFlags: 可以将隐式或者显示配置的参数传给虚拟机的参数输出(一般打印在最前面,输出该虚拟机当前的配置情况)。
建议:在实际工作中,我们可以直接将初始的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数以及减少以防内存不够而请求获取内存的操作等从而提高性能。

2.测试结果:
main方法测试代码:通过查看判断结果判断是否按照我们配置的参数那样
在这里插入图片描述
操作顺序:Run As --> Run Configurations --> 选择当前类(如果没找到当前类请先直接运行该类先)–>Run

在这里插入图片描述

打印结果
在这里插入图片描述
按照上面说的,我配置的参数意义是:初始堆空间大小5M,最大内存20M,输出GC详情,使用串行GC,输出命令行标签(意思就是在第一行输出你当前配置的参数,结果图里面有)
结果图输出说明:
首先初始化堆空间内存为5M,最大堆空间20M,因为还没使用内存,所以此时max memory=20M,free memory=5M,total memory大约6M左右(为啥,因为虚拟机本身运行会占用部分内存,但这不应该占用初始的内存,但属于使用的总内存里面)
然后系统创建对象,花费了1M的内存,此时最大内存还是等于20M这是不会变的,从free Memory里获取内存,所以free Memory减少1M,而total memory不变,为啥,因为此时你并没有申请内存,那1M内存是从已经初始化过的5M里面获取的。
最后系统创建对象,花费了4M的内存,此时的free memory勉强够用,但堆并不会让空闲内存变得那么小,怕突然对象溢出,所以直接向虚拟机申请需要的4M内存,所以基本上free memory基本不变,而申请过来的4M内存应算在总内存total memory里面,所以总内存变成了约10M。

堆内存溢出参数设置举例:
参数如注释那样配置:
-Xms2m -Xmx2m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=e:/Test02.dump
在这里插入图片描述
运行,该程序申请了5M内存空间,而虚拟机设置堆内存最大2M,出现内存溢出,此刻打印的错误信息已经出现在了我的e:/Test02.dump。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值