谷咕咕最近在准备面试,本来想多看看堆和栈的关系,看看发现又设计到gc(Garbage Collection)垃圾回收机制,发现盲区太多了,就去粗略的学习了一下jvm(java虚拟机),发现之前只会写程序,底层的东西真是太丰富了。
正常情况下我们编写helloworld.java通过javac编译成字节码文件helloworld.class。通过java命令,将类放到jvm(java虚拟机中运行)
1.一次编写到处运行:
计算机最后执行的是机器码。(jvm)可以将一个代码编译成适用于不同操作系统的机器码,通过不同的jdk(有不同的jvm)实现的。这就是为什么,我们安装对应的jdk不同的jdk版本。
这样实现了我们不需要改变程序,让jdk帮我们完成底层的修改。
2.jvm的组成
类装载子系统:将c程序放到方法区中。
运行时数据区(内存模型):堆,栈(线程),本地方法栈,方法区,程序计数器。
字节码执行引擎:执行一些GC(垃圾回收机制)。
方法区(元空间):常量和静态变量,类元信息(有哪些方法)。
堆中对象的头指针找到方法去的指令码的内存地址,把地址放到动态链接中。
程序计数器:放线程马上要执行的指令码(行号)内存地址。
native本地方法,时间线与c语言的交互。
本地方法栈:c语言中局部变量存放的位置。
栈(线程):存放局部变量的存储,,一个线程一个栈,不同的方法有不同的栈。先进后出的数据结构,main和compute先后进栈,compute执行结束出栈,然后继续执行main方法。栈中的对象类型局部变量,是有地址指向堆中。
局部变量表:创建局部变量,操作数栈中的值赋值给它。
操作数栈:临时存放数据
动态链接:就是存储指向该方法指令码的地址符号
方法出口:一个方法结束,返回到主方法的哪行指令码。
堆:存放new出的对象。(下面细细讲)
堆:启动600M,老年代近400M。
Eden:存放对象。放满之后通过 minor gc垃圾收集。没被销毁的放入Survivor区。
Survivor from:存放上一层的对象。放满之后通过 minor gc垃圾收集。没被销毁的放入to区。
Survivor to:存放上一层的对象。放满之后通过 minor gc垃圾收集。没被销毁的放入from区。
通过15次gc还没销毁的放入老年代(方法区的 静态变量,数据库连接池)。
老年代满了full gc后都是有用的内,就会内存溢出。
执行引擎,执行gc,在执行full gc的时候会停掉应用线程的gc,影响程序性能。
jvm调优的目的:
1.减产full gc的次数
2.减少full gc的时间
老程序启动慢,程序启动的时候加载类,导致元空间满了full gc。(Metadata GC Threshold)
解决方案:提前设置元空间放大。
jvisualvm(工具):查看计算机正在运行的java程序。
谷咕咕也是上网看的资料整理的,如果大佬们看到有不对的地方,请在评论区交流啊!!!
关注小谷哈。