JVM笔记

JVM虚拟机

内存划分

  • 线程私有:java方法栈,本地方法栈,程序计数器。

  • 线程共享:堆,方法区。(需要GC垃圾回收)。

java程序工作过程

  • 一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名),每个java程序都需要运行在自己的JVM上,然后告知 JVM 程序的运行入口,再被 JVM 通过字节码解释器加载运行。

  • JVM在初始运行的时候就已经分配好了方法区和堆,JVM每遇到一个线程就给他分配一个独立的java方法栈,本地方法栈,程序计数器;运行结束后释放java方法栈,本地方法栈,程序计数器,它们的生命周期是和这个线程是相同的。

JVM中各部分功能

  • 程序计数器:它只占一小部分内存区域,可以当做当前线程执行的字节码的位置指示器;循环,判断,异常处理等都是依靠程序计数器完成的。

  • 虚拟机栈(java方法栈):

    • java指令是由操作码(方法本身)和操作数(局部变量)组成。

      • 操作码是保存在栈中的。

      • 操作数中,如果是八大基本数据类型,则是保存在栈中,如果是对象类型,则是在栈中保存一个该方法地址,在堆中保存值,用的话直接调用。

    • 每个方法运行时会直接创建栈帧,栈帧用于存储局部变量表(包含了对应的方法参数和局部变量),操作栈(Operand Stack,记录出栈、入栈的操作),动态链接、方法出口等信息,每个方法被调用直到执行完毕的过程,对应这帧栈在虚拟机栈的入栈和出栈的过程。

      • 局部变量表所需的内存空间在编译期间完成分配,在方法在运行之前,该局部变量表所需要的内存空间是固定的,运行期间也不会改变。

      • 调用A方法,则把A方法的栈帧压入栈中,A方法调用B方法,则把B的栈帧压入,先进后出。

    • 在Heap 中分配一定的内存来保存对象实例,实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(以帧栈的形式保存在Stack中),在Heap 中分配一定的内存保存对象实例。

    • 对象实例在堆中分配好之后,会在栈中创建一个4字节的内存地址,指向堆中的该对象实例。

  • 方法区

    • 方法区是存方法的区域,静态方法在类加载的时候就会加载,方法区包含所有的class和static变量。

小结

1.分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。

2.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。

3.以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。

4.类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存。

JVM内存调优

查看堆空间大小分配(年轻代、年老代、持久代分配) 垃圾回收监控(长时间监控回收情况) 线程信息监控:系统线程数量 线程状态监控:各个线程都处在什么样的状态下 线程详细信息:查看线程内部运行情况,死锁检查 CPU热点:检查系统哪些方法占用了大量CPU时 内存热点:检查哪些对象在系统中数量最大

https://www.cnblogs.com/wangjzh/p/5258254.html JVM内存机制

https://www.jianshu.com/p/ae97b692614e#

你可能感兴趣的:(JVM笔记)