手机网站 做成app,wordpress 阅读小说,无极网站站怎么有的下不了,小金县建设局网站摘要#xff1a; 上周末搬家后#xff0c;家里的宽带一直没弄好#xff0c;跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带#xff0c;可以结束一个多星期没网的痛苦日子了。这段时间也是各种忙#xff0c;都一个星期没更新博客了#xff0c;再不写之前那种状…摘要 上周末搬家后家里的宽带一直没弄好跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带可以结束一个多星期没网的痛苦日子了。这段时间也是各种忙都一个星期没更新博客了再不写之前那种状态和激情都要慢慢褪去了总觉得心里慌的一逼这怎么行呢趁明天周末在公司电脑上记录下这周的一些学习内容。 上周末搬家后家里的宽带一直没弄好跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带可以结束一个多星期没网的痛苦日子了。这段时间也是各种忙都一个星期没更新博客了再不写之前那种状态和激情都要慢慢褪去了总觉得心里慌的一逼这怎么行呢趁明天周末在公司电脑上记录下这周的一些学习内容。近期在看一本很经典的java书籍《深入理解java虚拟机 第二版》几年前也翻过但那时候功力不够不太能看懂就没看了。现在回过头来看发现确实写的很好很多知识点都能理解了而且讲的也很有深度收获颇多。后期计划按照这本书的内容写出一系列博客来深入学习和复习下java虚拟机相关的知识。 一、JVM内存模型概述 JVM内存模型其实也挺简单的这里先提2个知识点 1、组成java堆java栈即虚拟机栈本地方法栈方法区和程序计数器。 2、是否共享其中方法区和堆区是线程共享的虚拟机栈本地方法栈和程序计数器是线程私有的也称线程隔离的每个区域存储不同的内容。这2个知识点必须牢记是掌握JVM内存模型的基础。 二、程序计数器 JVM中的程序计数器是一块很小的内存区域但是这块内存区域挺有意思的。主要特性有3个 1、存储内容对于java普通方法即没用native关键字修饰的方法存储的是执行过程中当前指令的地址而对于native方法这里是空的undefined为啥呢因为调用本地方法的时候可能已经超出了JVM虚拟机的内存地址了。 2、线程私有的为什么程序计数器是线程私有的根据存储内容也好理解假如是线程共享的那多个线程执行的时候都不知道自己当前线程执行的地址是哪个了有的线程快有的线程慢快的执行完就进入下一步等慢的线程执行完回来发现自己的地址都变了岂不乱套 3、是JVM中唯一不会报内存溢出OutOfMemoryError的区域。 三、虚拟机栈 虚拟机栈主要存储的是一个个栈帧每个栈帧中存储的是局部变量表操作数栈动态链接和方法出口信息等。其中局部变量表中存储的是方法中定义的一些局部变量对象的引用参数和方法的返回地址等。局部变量表所占用的空间大小在编译期就能确定在方法运行的时候并不会改变局部变量表的空间大小这结合局部变量表存储的内容就很好理解。操作数栈可以理解为对当前操作的数据入出栈对于64位长度的long和double类型每个操作数占用2个字宽slot其他类型的操作数占用一个字宽slot。每个方法调用时都会创建一个栈帧执行的过程对应的就是一个栈帧在虚拟机栈中从入栈到出栈的过程。有关栈帧的内容可以参考一个网友写的一篇博客https://blog.csdn.net/xtayfjpk/article/details/41924283讲的很好很详细。这里放个栈帧的图看了一目了然。 关于虚拟机栈内存溢出有2种情况 1、线程请求的栈深度 超过了虚拟机允许的深度会抛出StackOverflowError所以当我们在代码中看到这个异常时就应该想到可能是虚拟机栈出了问题。 2、如果虚拟机栈可以动态扩展当前大部分JVM都可以动态扩展不过JVM也允许固定长度的虚拟机栈当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。 四、本地方法栈 这块知识点比较简单本地方法栈和虚拟机栈的功能类似只不过是为JVM调用native方法时服务的而且JVM对本地方法使用的语言比如Java调用C语言实现的功能就需要定义native方法来实现、使用方式和数据结构都没有强制规定因此不同的虚拟机可以自由实现。而且HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一。与虚拟机栈类似本地方法栈也会抛出StackOverflowError和OutOfMemoryError。 五、方法区 方法区是一个比较重要的区域java虚拟机规范中把方法区描述为堆的一个逻辑部分但是为了和Heap堆区对应也称Non-Heap非堆区。主要存储的是静态变量常量包括运行时常量类的加载信息和java编译后的代码。这部分空间不需要连续可以选择固定大小和可扩展通常在这部分是没有GC的因为GC回收的都是些静态变量常量和类的加载信息这些对象回收效果通常不尽人意因此可以选择不实现垃圾回收。这块区域也称为持久代当这块内存不足时也会报OutOfMemoryError异常。 六、堆区 Java堆区是JVM内存中最胖的一块区域因为这里存储的都是对象的实例和数组对象。这块区域是线程共享的在JVM启动时就会创建想想如果这么大的空间是线程私有的那内存不得爆掉吗按照java虚拟机规范堆区的内容可以物理上不连续只要逻辑上连续即可在实现时可以是固定大小的也可以是可扩展的而且通常都是可扩展的我们常用的内存参数-Xms和-Xmx就是用来调节堆大小的。java堆区按生命周期不同分为新生代和老年代。新生代又可以细分为Eden和Survivor区而Survivor又可以细分为Survivor1和Survivor2这两者通常只使用其中一块另一块用来GC时保留存活的对象。大部分的new出来的对象都是存放在Eden区如果是大对象比如一个很大的数组或者List对象可以通过JVM参数-XX:PretenureSizeThreshold将超过指定大小的对象直接存入到老年代需要注意的是写程序时应该尽量避免朝生夕死的大对象进入老年代因为相比年轻代的GC老年代GC的成本更大。Eden和Survivor的默认大小比值的8:1:1新生代默认的GC算法是复制算法。老年代的默认GC算法是标记整理法。关于这2种GC算法会在下篇博客讲解。
当堆中没有足够内存时会抛出OutOfMemoryError异常。关于堆区的内存模型可以参考下面的图片 原文链接
本文为云栖社区原创内容未经允许不得转载。