目录
JVM的位置在哪
高级语言-》汇编语言-》机器指令
下面就是学习JVM这个框里面的东西,从里面有什么东西开始学
JVM 包括哪几部分
我们一般说的jvm调优,就是运行时数据区里面进行调优
堆
堆这个框里面,分为以上的这些区,当我们创建的对象,首先是对放在伊甸园区,当伊甸园区放满了,执行引擎会默默的创建一个线程,这个线程就是垃圾回收线程,这个垃圾回收线程就会在伊甸园区进行回收没有用的对象
垃圾回收线程如何工作的
首先是要找到垃圾之后,才可以回收。如何找垃圾,如何回收呢?
如何找垃圾
之前的版本是引用计数器算法,现在新版本是可达性分析算法‘
利用这些算法进行找垃圾
可达性分析算法
也就是只要创建了这个垃圾回收线程,那么这个垃圾回收器就会从我们的线程里面找很多的变量,把全部的变量都找到,比如在栈里面找变量,在方法区里面找变量等,这些找到的变量就是我们说的根节点,然后从这些根节点开始,看看整个线程中,哪些地方用到这些变量,也就是哪些对象引用了他们,一直往下找,在这个引用链条上面的就是非垃圾,把他们放到幸存0区,留在伊甸园的就是垃圾了。
栈
里面主要是放局部变量,只要有一个线程开始运行,那么Java虚拟机就会从这个Java栈里面挖一块地方,给这个线程,以后这个线程里面的局部变量就会放到这个挖出来的Java栈里面。
这个Java栈里面有很多的小块,就是栈帧,意思是每一个线程开始执行,Java虚拟机给这个线程挖出一个Java栈,在这个线程执行过程中,这个线程里面有很多的方法,也就是这个线程会调用很多的方法,每一个方法里面都会有很多的变量。所以没执行到一个方法的时候,挖出来的Java栈里面就会再挖出一小块地方,专门放这个方法里面的变量。
执行方法就是入栈,执行完成就是出栈
一句话总结:
一个方法对应一块栈帧区域
栈帧里面有什么
栈帧里面除了放局部变量,里面还可以放这些东西。
局部变量:
就是我们定义的变量
操作数栈:
就是我们定义的变量的值,我们要对这些值进行操作,这些值需要一个地方放,就在这个区间
动态链接:
存放当前方法在方法区的地址
方法出口:
里面保存的是,当前方法执行完成之后,返回到主函数的位置,也就是执行完成之后,返回后在主函数的哪个地方开始执行,不能从头开始吧。
变量的值不仅仅是数字,字符串等,还有可能是对象,对象是在堆里面的,所以当前的变量的值就是对象在堆里面的地址
程序计数器
每一个线程都有一个自己的程序计数器,里面存放的是 当前需要执行的指令的地址。(代码在方法区的内存地址)
由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。
每一个线程独有的,只有Java虚拟机给一个线程开辟了一个Java栈,那么也会从程序计数器上面挖出一块地方,给这个线程。
为什么要有这个程序计数器
程序计数器的值是谁修改的
我们的class文件,被类加载器加载到运行时数据区里面的方法区,这个方法区内容会被 执行引擎进行执行,执行引擎执行到哪步,就会把地址存到程序计数器里面。
也就是这个值是被执行引擎进行修改的
方法区
什么是常量:
什么是静态变量:
这个对象是在堆里面存放的,user就是静态变量放在方法区,值就是地址
本地方法栈
如果你写的程序里面,使用了Native修饰这个方法,或者底层使用了这个关键字修饰的方法,那么Java虚拟机进行加载的时候,就会把这个方法加载到这个本地方法栈里面。说白了,就是被Native修饰的方法,就会到这个里面。
Native关键字:
我们自己写一个线程,调用start()进行启动,这个启动的方法的源码里面是调用native修饰的start0()方法
既然是native修饰的方法。就是其他语言的方法
意思是只要利用java操作其他语言,或者硬件,比如打印机,那么就需要这个本地方法栈,就需要这个关键字native
jvm调优入门
我们先写一个Java代码,让他内存溢出
垃圾回收器首先找到heapTests这个根节点,他引用的都不能被回收,因为其他的对象都被他引用的,只要他还在工作,那么都不能被回收,现在是一直创建对象,所以,有可能内存溢出。
我们打开jdk自带的调优工具
输入以上的命令,就会打开一个界面
jvisualvm
这个工具就会找此时此刻,所有的正在运行的Java进程
我们的代码正在执行,所以我们可以看到这个工具里面,以下这个就是我们的执行的代码