Jvm学习整理

jvm特点:Java语言编译程序只需要生成能在Jvm上运行的目标代码(字节码),就可以在其他平台上不加修改的直接运行,Jvm在运行字节码的时候,把字节码解析成具体平台上的操作指令



操作系统的堆和栈

堆:一般是有程序员分配释放,若不释放,程序结束时则由os回收,分配方式类似于链表

栈:有操作系统自动分配释放,存放函数参数值,局部变量值等


Jvm内存图


Jvm位于操作系统的堆当中,类加载到虚拟机的过程:当classloder启动的时候,它会去主机硬盘上,将A.class文件加载到Jvm方法区,在方法区中这个字节文件会被虚拟机拿来new A字节码,然后在堆内存当中生成一个A字节码对象。然后A字节码这个内存文件有俩个引用,一个指向A的class对象,一个指向加载加载自己的classloader

Jvm堆和栈的特点:

栈:函数中定义的基本类型的变量,对象的引用都在栈内存中分配。数据执行完毕,变量就会被释放,栈的更新速度快,因为局部变量的生命周期短。栈是数据共享的

堆:用于存储new出来的对象和数组,是由jvm垃圾回收机制不定时回收的。堆是线程共享的

分析数据共享

int a = 3; 

int b = 3; 

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况,即共享了3这个栈数据。

对于String类型来说,编译期已经创建好的(String a="123" ,双引号定义的内容)存在常量池里面,如果是运行期则存在堆中(String b=new String("123"),new 出来的对象),而等号的左边为引用对象。

对于栈和常量池中的数据可以共享,即可以有多个引用对象;而对于堆来说,数据不可以共享,只能有一个引用对象。

再来分析线程共享:

所有线程共享堆,但每个线程都有自己的寄存器和自己的栈。

最后总结一下数据共享的有栈、寄存器、PC,线程共享的有:堆、全局变量、静态变量、方法区。




Jvm的内存组成:

1.程序计数器(pc寄存器):

    用于保存程序当前执行的指令地址。当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令.每个线程都会有自己独立的程序计数器,并且不相互影响,在JVM规范中规定,如果线程执行的是native方法,那么程序计数器保存的值是undefined.还有就是程序计数器中内存的数据所占用的空间大小不会随着程序的执行而改变,因此对于程序计数器这块内存是不会发生OOM的.

2.堆:用于存放new出来的对象会数组,线程共享的,jvm启动的时候创建,是jvm挂美丽内存最大的一块.。可以通过设置-Xmx和-Xms的值来控制,堆内存当中又可以划分为:

    a.新生代(young ):新生代又可以分为Eden区和Survivor,新生代的大小可以由-Xmn来控制,也可以由-XX:SurvivorRatio来控制Eden和Survivor的比例

        a1.Eden:新建的对象都是用新生代分配内存空间

        a2.Survivor:当Eden空间不足时,会把存活的对象转移到Survivor

  b.旧生代:用于存放新生代经过多次垃圾回收依然存活的对象

  c.持久代(Permanent Space):  实现方法区,但不等同于方法区,只不过是Hotspot JVM用Permanent Space来实现方法区而已,有些虚拟机没有Permanent Space而用其他机制来实现方法区。用于存放已加载的类信息,方法信息,常量池等。

java.lang.OutOfMemoryError:Java heap space异常,说明Java虚拟机的堆内存不够,

原因:

        1.java虚拟机的堆内存设置不够,可通过参数-Xms,-Xmx来调整

        2.代码中创建了大量对象,并且长时间不能够被垃圾收集器收集

java.lang.OutOfMemoryError:PerGen space,说明java虚拟机对永久代设置不够

        1.程序启动需要加载大量的第三方jar包,例如:在一个tomcat下部署了大量应用

        2.大量动态反射的类不断被加载

3.栈:栈分为虚拟机栈和本地方法栈

    虚拟机栈:其中存放每个方法执行时创建的栈桢,每个线程执行每个方法的时候都会在栈中申请一个栈桢,每个栈桢包括局部变量区,操作数栈,动态链接,方法返回地址,使用-Xss设置每个线程的大小

局部变量表:存储基本类型的变量和对象的引用,内存是在编译期间分配的,在运行期间不会改变大小

操作数栈:程序在执行过程中的计算都是通过操作数栈来完成的

动态链接:每个栈桢包含一个指向运行时常量池的引用,Class文件常量池中包含大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的引用为参数,这些引用在运行时转化为直接引用,称为动态连接

方法返回地址:每个方法执行完毕之后要返回之前执行他的地方,因此栈桢中需要保存一个方法的返回地址


    本地方法栈:用于支持native方法的执行

4.方法区:虚拟机启动时创建,线程共享,用于存放将要加载的类信息,静态变量,final类型的常量,属性和方法信息。



类加载机制


1.Bootstrap ClassLoader

    负责加载$JAVA_HOME中 jre/lib/rt.jar里所有的class,由c++实现,不是classLoader子类

2.Extension ClassLoader

    负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中 jre/lib/*.jar 或者 -Djava.ext.dirs指定目录下的jar包

3.App ClassLoader

    负责加载classpath中指定的jar包及目录中的class

4.Custom ClassLoder

    属于应用程序根据自身需要自定义的ClassLoader

双亲委派模式:某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成加载任务就成功返回,只有父类加载器无法完成此加载任务时,才自己去加载

Jvm垃圾回收:

    jvm采用gc分代收集算法:将jvm堆分为新生代和老年代,根据各个年代的特点采用最合适的算法,新生代中,存活对象较少,所以采用复制算法,老年代中对象的存活率较高,而且没有额外的空间分配担保,所以采用标记清除算法

垃圾收集器

Serial收集器:新老生代都是串行收集 -XX:+UseSerialGC

ParNew收集器:

    新生代多线程(复制算法),老生代单线程(标记-整理算法)

    -XX:+UserParNewGC  ParNew收集器

    -XX:+ParallelGCThreads 限制线程数,默认是cpu核数

Parallel收集器:

    新生代多线程(复制算法),老生代单线程(标记-整理算法)

    -XX:+UserParallelGC  Parallel收集器

Parallel Old收集器:

    使用多线程和标记-整理算法

    -XX:+UserParallelOldGC

 CMS收集器:

    采用标记-清除算法

    优点: 并发收集、低停顿 

    缺点: 产生大量空间碎片、并发阶段会降低吞吐量

    -XX:+UseConcMarkSweepGC 使用CMS收集器

    -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长

    -XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理

    -XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量)

G1收集器

    空间整合,G1收集器采用标记整理算法,不会产生内存空间碎片,可预测停顿

    -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC #开启;

    -XX:MaxGCPauseMillis =50 #暂停时间目标;

    - XX:GCPauseIntervalMillis =200 #暂停间隔目标;

    -XX:+G1YoungGenSize=512m #年轻代大小;

    -XX:SurvivorRatio=6 #幸存区比例

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容

  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,500评论 3 83
  • Java 虚拟机有自己完善的硬件架构, 如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 屏蔽了与具体操作系...
    尹小凯阅读 1,673评论 0 10
  • 内存溢出和内存泄漏的区别 内存溢出:out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,...
    Aimerwhy阅读 722评论 0 1
  • 第二部分 自动内存管理机制 第二章 java内存异常与内存溢出异常 运行数据区域 程序计数器:当前线程所执行的字节...
    小明oh阅读 1,120评论 0 2
  • 工作之余,想总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的...
    Huang远阅读 626评论 0 2