一、Java代码运行原理

  1. .java编译变成.class文件。

  2. 类加载器把.class字节码文件加载到JVM中。

  3. JVM中的字节码执行引擎从指定的main()方法开始执行代码。

二、类被加载的时机

代码中使用到这个类的时候就会被加载。包含main()方法入口的主类,一定会在JVM进程启动之后就加载,而其他的类会在执行时用到了再加载。

三、JVM中的两大对象

  1. 字节码对象:类被加载到内存的时候生成,只有一个,存储类结构信息,放在元数据区,可以被回收,通过User.classClass.forName("com.xxx.User")user.getClass()方式获取。

  2. 实例对象:是乐观事物在内存中的呈现,可以有多个,一般放在堆中,可以被回收,通过new、反射方式获取。

类实例对象引用Class对象,Class对象双向引用类加载器。系统类加载器引用的class对象在整个JVM生命周期中都不会被回收。

Class对象什么时候被回收?

首先该类在堆中的所有实例对象被回收,其次该类的ClassLoader被回收,最后该类的Class对象没有任何引用就会被回收。

四、类的使用过程

  1. 加载:把磁盘的.class文件加载到内存。

  2. 验证:校验是否符合JVM规范。

  3. 准备:给类和类变量分配内存空间,并给类变量赋默认初始值,就是说在方法区/元数据区中创建Class对象。

  4. 解析:把符号引用替换成直接引用。

  5. 初始化:执行类变量的赋值逻辑,来替换掉之前的初始默认值,另外也会执行static静态代码块。

  6. 使用:通过new、反射等方式实例化后使用。

  7. 卸载:没有被引用后就会被GC回收,到一次使用到时会再次被加载。

若有父类则会先加载父类,再加载子类。

五、类的创建过程

  1. 加载父类,为父类类变量分配内存并赋初始值。

  2. 加载子类,为子类类变量分配内存并赋初始值。

  3. 执行父类类变量的赋值运算,以及静态代码块(哪个在前哪个先执行)。

  4. 执行子类类变量的赋值运算,以及静态代码块(哪个在前哪个先执行)。

  5. 新建父类实例,为父类实例变量分配内存并赋初始值。

  6. 新建子类实例,为子类实例变量分配内存并赋初始值。

  7. 执行父类的实例变量赋值运算。

  8. 执行父类的构造方法。

  9. 执行子类的实例变量赋值运算。

  10. 执行子类的构造方法。

六、类加载器

  1. 启动类加载器:加载JDK安装目录lib下的核心类。

  2. 扩展类加载器:加载JDK安装目录lib/ext下的类。

  3. 应用程序类加载器:加载classpath目录下的类,也就是你写的应用程序。

  4. 自定义类加载器:根据需要自定义加载指定的类。

七、双亲委派加载机制

  1. 子类加载器询问父类加载器能否加载?

  2. 父类加载器询问父父类加载器能否加载?直至顶级类加载器。

  3. 顶级类加载器发现在自己的加载范围内没有该类,则让父类加载器去加载。

  4. 父类加载器发现在自己的加载范围也没有找到该类,也继续让子类加载器去加载。

  5. 这时子类加载器发现自己加载范围内有该类则加载。

这样设计的目的是防止重复加载。

八、JVM构造图

九、线程公有区

  1. 方法区:也叫永久代,存在于jdk1.8以前的版本,1.8及以后版本用「元数据区」代替,是物理内存中的一块空间。用来存放类结构信息(Class对象)、类变量、常量池等。

  2. 堆区:用来存放实例对象,包括类变量、实例变量、局部变量引用的对象。分为年轻代老年代。年轻代又分为一个Eden区两个Survivor区。一般一开始创建的对象实例,都会被放在年轻代,经过了15次Minor GC后,依然存在的长期引用对象就会被移到老年代。直至老年代也满了就会发生Full GC。

一些非常大的对象可能会直接分配在老年代。

十、线程私有区

  1. Java方法栈:每个线程都有一个方法栈,每个方法会有一个栈帧,里面包含局部变量。方法开始执行,栈帧压入方法栈,执行结束,栈帧弹出方法栈。

  2. 本地方法栈:Java会通过native修饰的本地方法,调用操作系统的C/C++类库。这些方法也有一个线程私有的方法栈,作用和Java方法栈一样。

  3. 程序计数器:每个线程都有一个程序计数器,用来记录字节码执行的位置。

栈就好比如一个桶,压栈和弹栈遵循「先进后出」的顺序。

十一、垃圾回收的区域

  1. 堆区、方法区(元数据区)都可能会发生GC。堆区回收的实例对象,方法区回收的是Class对象。

  2. 方法栈不会发生GC,栈帧出栈后即会被销毁,局部变量就不存在了,堆中的对象就会失去引用,垃圾回收线程就会回收堆中没有被引用的对象。

十二、JVM内存核心参数

  1. -Xms:堆内存大小

  2. -Xmx:堆内存最大大小

  3. -Xmn:堆内存中新生代大小,扣除新生代剩下的就是老年代的内存大小

  4. -XX:PermSize:永久代(方法区)大小

  5. -XX:MaxPermSize:永久代最大大小

  6. -Xss:每个线程的栈内存大小

  7. -XX:MetaspaceSize:元数据区(1.8版本后,替代了方法区)大小

  8. -XX:MaxMetaspaceSize:元数据区最大大小

设置JVM参数方法:
java -Xms512M -Xmx512M -Xmn256M -Xss1M -XX:PermSize=128M -XX:MaxPermSize=128M -jar xxx.jar

十三、JVM调优内容

优化内存分配,降低垃圾回收,特别是Full GC的频率,减少垃圾回收的时间,降低垃圾回收对系统运行的影响。

思路:

  1. @Service等标注的常驻对象尽快进入老年代,以免留在年轻代占用空间。

  2. 避免让只使用一两次的短期对象(如订单对象)进去老年代,从而频繁发生Full GC。

十四、估算JVM内存压力

以支付系统为例,在部署了多个节点情况下,估算评论每个节点的压力:

  1. 估算高峰期每秒钟处理多少个请求,如30个。

  2. 估算每个请求处理耗时多久,如1秒,那么1秒之后这个请求产生的对象都是没有被引用,是可以被回收的对象。

  3. 估算每个请求产生的对象占用多大的内存空间,如支付订单对象,按20个实例变量,Integer类型4个字节,Long类型8字节计算,一个订单对象顶多500字节。

  4. 那么30个订单就是:30×500字节=15000字节,大概就是15kb。

  5. 考虑到系统还会创建其他对象,放大10~20倍,也就是每秒钟产生的对象大小在几百kb~1MB之间。

  6. 那就按照1MB估算,也就是每秒钟大概创建1MB的对象放在年轻代里,1秒钟之后成为垃圾对象,等待回收。

  7. 结合系统设置的年轻代的大小,就可以估算出大概多久就会占满,发生GC。

十五、JVM常见的设置数值范围

  1. 机器采用4核8G

  2. 堆内存3G,年轻代2G

  3. 方法区(永久代)/元数据区,几百MB,如256M

  4. 线程栈内存一般保留默认,如512KB到1MB

十六、年轻代的构成

  1. 一个Eden区(伊甸园区)

  2. 两个Survivor(幸存区)

  3. 比例默认是8:1:1

十七、对象是否能被回收

  1. 可达性分析算法,从GC Root开始,向下搜索,如果一个对象到GC Root没有任何引用,没有形成引用链,那么该对象可回收。

  2. GC Root(局部变量静态类变量,实例变量不是)。

十八、引用类型

  1. 强引用:平常的写法就是强引用,如Object obj = new Object(),不会被回收

  2. 软引用:SoftReference,内存不足会回收

  3. 弱引用:WeakReference,会被回收

  4. 虚引用:省略

有GC Root不回收,没有GC Root会被回收。
如果我GC Root,但是是软引用或者弱引用,也可能被回收。

十九、垃圾回收算法

  1. 复制算法:用在年轻代,把幸存对象从E区复制到S区,在清空E区。

  2. 标记整理算法:用在老年代,标记幸存的对象,并整理移动到一起,清空余下的内存,避免产生过多的内存碎片。

  3. 标记清除算法:用在老年代,会产生大量内存碎片。

二十、对象何时由年轻代进入老年代?

  1. 默认15次Minor GC后仍未回收掉的

  2. 动态年龄判断,年龄1+年龄2+年龄n的对象总大小大于S区大小的一半,那大于等于年龄n的对象都会移到老年代。

  3. 大对象直接进去老年代,如1M以上

  4. Minor GC后存活对象总大小大于S区大小,直接转移到老年代

二十一、何时触发Minor GC?

  1. Minor GC的触发时常发生,当年轻代的Eden区满了就会触发一次Minor GC

二十二、何时触发Full GC?

  1. 在执行Minor GC前,会检查老年代剩余空间是否大于年轻代里所有对象总大小。

  2. 没配置空间担保机制(未开启HanderPromotionFailure参数),如果不大于,则执行Full GC。

  3. 配置了空间担保机制,再判断老年代剩余空间是否大于历次Minor GC后进入老年代的平均大小,如果不大于,则执行Full GC。如果大于,则冒险执行Minor GC。

  4. 上面冒险进行了Minor GC后,如果存活对象大小大于Survivor区,需要转移到老年代,若这时老年代剩余空间不够,就是空间担保失败,则执行Full GC。

  5. 如果方法区(元数据区)达到了最大的内存阈值,也会触发Full GC。

  6. 老年代使用率达到了92%的阈值,也会触发Full GC。

在jdk1.6之后废除了-XX:HandlePromotionFailure参数(默认开启空间担保),只要判断“老年代可用空间” > “年轻代对象总和”,或者“老年代可用空间” > “历次Minor GC升入老年代对象的平均大小”,两个条件满足其中一个就可以进行Minor GC,不需要提前触发Full GC。

二十三、垃圾回收器

  1. Seril:年轻代,单线程,效率低

  2. Serial Old:老年代,单线程,效率低

  3. ParNew:年轻代,多CPU并行回收

  4. CMS:老年代,多线程并发回收

  5. G1:最新的,并行与并发兼备,适合年轻代和老年代分代回收,适合超大内存的机器,适合要求低延迟的业务场景。

二十四、Stop The World

垃圾回收线程进行GC时,会停止所有工作线程。

二十五、如何做到仅仅发生Young GC(Minor GC),几乎没有Full GC?

结合系统的运行,根据内存的占用情况,GC后的对象存活情况,合理分配Eden、Survivor、老年代的内存大小,合理设置一些参数,即可做到。

二十六、ParNew原理(复制算法)

  1. 新对象优先放在E区。

  2. 发生第一次Minor GC,存活对象移到S1区,清空E区。

  3. 新对象继续放在E区。

  4. 发生第二次Minor GC,把E区和S1区的存活对象移到S2区,清空E区和S1区。

  5. 新对象又放在E区。

  6. 发生第三次Minor GC,把E区和S2区的存活对象移到S1区,清空E区和S2区。

  7. 如此循环往复,每经历过一次Minor GC,对象年龄就累计增加一岁。

ParNew垃圾回收器和Serial垃圾回收器相比,是并行的,默认有多少个核就我多少个线程回收,所以在多核CPU时是占优势的。

二十七、CMS原理(标记清理算法)

标记清理算法,就是从GC Root出发使用可达性分析算法,判断老年代里面的各个对象是否存活。先把垃圾对象都标记出来,然后一次性把垃圾对象都清理掉,最后再整理剩余的存活对象挨着放到一起。分为4个阶段:

  1. 初始标记:工作线程停止,进入STW,只标记被GC Root直接引用的对象,速度很快。

  2. 并发标记:工作线程继续运行,对老年代所有对象进行GC Root追踪,速度很慢。

  3. 重新标记:工作线程停止,进去STW,对第二阶段中被程序系统运行变动过的少数对象进行标记,速度很快。

  4. 并发清理:工作线程不停止,并发清理掉上面标记出来的垃圾对象,速度很慢。另外这时工作线程运行产生的垃圾对象无法被清理,成为「浮动垃圾」。

  5. 碎片整理:把回收后存活的大批对象整理到一起,避免产生过多内存碎片。

二十八、为什么Full GC 要比Minor GC慢很多?

  1. 年轻代里面99%都是垃圾对象,通过GC Root追踪到1%的存活对象很快,复制到S区也很快,整块E区都清除也很快。

  2. 老年代里面存活对象很多,在并发标记阶段完成GC Root追踪很耗时,另外清理内存中零散的垃圾对象也很慢。清理完后还要把存活对象整理到一块,也很慢。在并发清理的时候,万一有对象一进来,但空间不够放了,这时候就会切换Serial Old回收器,速度更慢。

二十九、G1原理

  1. 分为一个个区(Region),Region由G1动态分配给年轻代、老年代。

  2. G1计算每一个Region内可回收的的对象大小和预估时间,在垃圾回收的时候,挑选“最少时间内能回收最多对象”的Region进行回收。

  3. 关键参数-XX:MaxGCPauseMills控制系统停顿时间。

  4. 每个Region大小由G1自动分配,最多2048个,大小是2的倍数,如1M/2M/4M等。如堆大小是4096M,则除以2048,则每个Region是2M。

  5. 初始时默认新生代占堆内存5%,随着系统不断运行,G1不断给新生代添加更多的Region,最多不超过60%

  6. 新生代垃圾回收后又会有空余出Region,动态地被分配给其他区。

  7. 新生代也会有E区和两个S区,一样是在新生代的Eden满的时候触发新生代垃圾回收,也是用「复制算法」,也会停止工作线程,进入STW状态。

  8. 但这里的Young GC不是回收新生代的所有空间,而是根据设定的最大的停顿时间,只回收部分性价比最高的Region

  9. 新生代对象一样也是在熬过了一定次数的Minor GC后,或者是触发了动态年龄判定规则后,或者是存活对象在Survivor区放不下后,转移到老年代中。

  10. 但是这里大对象不再进入老年代,而是分配到单独的Region。

  11. 当老年代对象越来越多,占据堆内存的45%的时候,会触发新生代+老年代的混合垃圾回收,即Mixed GC

G1垃圾回收器最大的优势就是可以让用户设置最大系统停顿时间,减少由Stop The World对系统带来的卡顿,它能根据设定的停顿时间去回收部分的Region,不会像ParNew、CMS回收大内存时因为存活对象过多而导致太慢。因此G1特别适合用在要求低延迟大堆内存的场景。

三十、G1混合回收过程(Mixed GC)

  1. 初始标记:停止工作线程,从GC Root开始搜索,标记能直接引用的对象。

  2. 并发标记:允许工作线程执行,对第一阶段标记的对象进行GC Root追踪,找出所有存活的对象。并且记录对对象的修改,如哪个对象被新建了,哪个对象失去了引用。

  3. 最终标记:停止工作线程,根据上面并发标记阶段记录的对象修改,最终标记哪些是垃圾对象,哪些是存活对象。

  4. 混合回收:会停止所有工作线程,先计算回收性价比,也就是计算每个Region中垃圾对象数和执行垃圾回收的预期性能和效率,再根据设定的系统停顿时间,选择性价比最高的部分Region进行回收。(注意:在混合回收时,无论是新生代还是老年代,都是采用复制算法,即把存活对象拷贝到空余Region,然后在清理要回收的Region,但是这个时候要是没有空余的Region了,就会触发回收失败,这时候就会切换到Serial Old单线程回收器,这效率是非常慢的。)

老年代占用大小达到堆内存45%的时候就会触发Mixed GC,不仅仅回收老年代,还会回收新生代、以及大对象的Region。而且最后的混合回收阶段回执行多次,也就是先停止工作,执行一次混合回收,接着恢复系统运行,然后再次停止工作,执行混合回收,默认是如此反复执行8次。但如果新生代回收空闲出来的Region达到默认的堆内存的5%,就会停止混合回收。

三十一、G1常用参数

  1. -XX:+UseG1GC:指定使用G1垃圾回收器

  2. -XX:MaxGCPauseMills:每次GC系统最大停顿时间(关键),默认200ms

  3. -XX:G1HeapRegionSize:每个Region大小

  4. -XX:G1NewSizePercent:初始化时默认新生代对堆内存占比,默认5%

  5. -XX:G1MaxNewSizePercent:最多新生代对堆内存的占比,默认60%

  6. -XX:SurvivorRatio:新生代E区和两个S区的比例,默认是8,即8:1:1

  7. -XX:MaxTenuringThreshold:在新生代能躲过GC的最大年龄,默认是15

  8. -XX:InitiatingHeapOccupancyPercent:触发混合回收的老年代对堆内存的占比,默认45%

  9. -XX:G1MixedGCCountTarget:混合回收阶段执行几次混合回收,默认8次

  10. -XX:G1HeapWastePercent:空余的Region达到对堆内存占比多少会停止混合回收,默认5%

  11. -XX:G1MixedGCLiveThresholdPercent:选择Region进行回收的时候,必须存活对象低于多少占比的Region才能回收,默认是85%

三十二、JVM调优思路

jvm优化的主旋律就是,尽量让短命对象在新生代回收掉,长期存活对象早进入老年代,G1的优化思路亦是如此。

  1. 首先是根据具体业务系统,合理分配老年代和新生代的大小、新生代Eden和Survivor区大小

  2. 其次是根据具体业务系统,合理设置G1的MaxGCPauseMills大小。太小容易造成回收频繁,影响系统的吞吐量。太大会增大系统的停顿时间,影响用户体验

JVM内存优化就是,了解自己的系统运行的内存模型,估算合理的单位时间内产生的对象大小,然后分配合理的新生代和老年代内存空间,尽可能让普通的对象在新生代中,不进入老年代。

三十三、传统垃圾回收器和G1垃圾回收器调优的区别

调优思路还是减少耗时的垃圾回收,也就是避免对象进入老年代。

传统的垃圾收集器是通过调整s区和e区的大小来控制,而G1则比较先进,直接指定一个期望的停顿时间。

选择停顿时间的标准是既不能频繁触发minor gc,也不能一次回收过多的对象,所以还得通过工具来调试出一个最适合自己系统的停顿时间。

通过工具检测,要得出一个停顿多久可以回收多少的内存大小的指标。根据这个指标和业务系统生成垃圾的速率设置合理的停顿时间。

三十四、为什么说G1垃圾回收器调整系统停顿时间参数很重要?

  1. 过小,每次能回收的Region太少,会频繁触发GC。

  2. 过大,每次能回收的Region太多,存活对象太多,可能新生代gc过后 存活对象太多,导致survivor放不下,进入老年代 或者因为动态年龄进入老年代。

其实Mixed GC就是由于最大系统停顿时间设置得不合理导致的。

三十五、一些名词解释

  1. Young GC、Minor GC相同,都是指年轻代的GC

  2. Old GC单指老年代的GC

  3. Full GC是针对年轻代、老年代、永久代(方法区)的整体的GC

  4. Mixed GC是G1垃圾回收器中针对年轻代、老年代以及大对象的Region执行的整体的混合回收,是G1特有的名词

  5. Major GC,有人把它等同于Old GC,有人把它等同于Full GC

三十六、JVM调优常用命令行工具

  1. jps | grep cipos-work,查看java进程PID。

  2. jstat -gc PID,查看JVM内存使用情况以及GC情况。

  3. jmap -heap PID,打印堆内存参数。

  4. jmap -histo PID | grep com.suntek,查看内存对象的大小。

  5. jmap -dump:live,format=b,file=dump.hprof PID,生成堆内存快照。

  6. jhat dump.hprof -port 7000,启动jhat服务器,以图形化方式分析堆内存对象分布方式。

  7. jstack,查看线程快照

  8. jconsole,可视化监控

  9. jvisualvm,可视化监控,可分析堆内存快照

  10. 常用监控平台,Zabbix,Open-Falcon

  11. MAT工具,分析堆内存快照,找到当时当时占用内存最大的对象是谁,有谁在引用它

三十七、明确JVM运行情况

  1. 新生代对象增长的速率

  2. Young GC的触发速率

  3. Young GC的耗时

  4. 每次Young GC后有多少对象存活

  5. 每次Young GC后有多少对象进入老年代

  6. 老年代对象增长的速率

  7. Full GC的触发频率

  8. Full GC的耗时

三十八、JVM终极面试问题

  1. 你们生产环境的系统的JVM参数怎么设置的?为什么要这么设置?

  2. 你在生产环境中的JVM优化经验可以聊聊?

  3. 说说你在生产环境解决过的JVM OOM问题?

三十九、内存泄露

很多对象使用过后仍是存活的,还引用着,没有及时被回收掉,占用的内存得不到释放。

四十、内存溢出(OOM)

  1. 内存溢出,即内存放不下了就会发生OOM

  2. 方法区(元数据区)、堆内存、java线程栈内存都可能会发生OOM

四十一、方法区(元数据)OOM原因

方法区(元数据区)主要放的是Class对象自己常量池等,Class对象能被回收的前提是:类加载器被回收、所有的实例被回收。此处发生OOM原因:

  1. 没有合理设置大小,通常256M或512M够用

  2. 用cglib等技术胡乱创建了很多动态代理增强类。

四十二、线程栈内存OOM原因

无论是不是同一个方法每调用一次都会产生一个栈帧压入栈中,方法递归调用时写得不好就会出问题。

线程栈内存通常1M足够

四十三、堆内存OOM原因

新对象优先放在年轻代的Eden区,每次Young GC过后,满足年龄次数、符合动态年龄判断规则、大于Survivor区的对象都会进入到老年代,老年代的大小达到一定阈值就会触发Full GC,回收完后空间仍然不够放就会OOM。

四十四、造成OOM的一些案例

  1. 告警计算系统,计算造成后推送到kafka让其他系统消费,kafka故障推送失败后数据留在内存中,造成堆内存溢出。

  2. 系统启动时没有设置元数据的大小,采用系统默认的,导致元数据区内存不够用,设置成125m后正常。

  3. 使用Cglib的Enhancer类实现动态代理机制的时候,没有把Enhancer对象缓存起来,导致不断创建新的增强子类,从而元数据区内存溢出。

  4. 采集核心日志推送ES,在推送失败在catch中重复调用推送方法,导致线程栈内存溢出。

  5. max-http-header-size表示最大允许请求头大小,默认是8kb,由tomcat线程引用,设置多大就会创建多大的byte数组,请求外部系统timeout设置为4秒,外部系统挂了请求就会阻塞4秒,并发过多导致堆内存溢出,解决方法是timeout设置为1秒,调小max-http-header-size参数。

  6. 查询数据库不加where条件导致查询数据太多而堆内存溢出。

  7. Kafka消费者批量拉取消息放入List中,再list放入队列中去进行也许处理,导致积压大量超大对象,造成Full GC。改成用定长阻塞队列,直接把数据一条条放入队列,不再包装成list,队列放满就停止拉取,等业务逻辑处理完再继续拉取。

JVM(Java虚拟机模型、Java运行时数据区模型)相关推荐

  1. Java 虚拟机学习笔记 | 运行时数据区总结

    前言 要想学习好 Java,Java虚拟(JVM)的学习是绕不开的.学习 Java虚拟(JVM)首先就要先了解的就是Java虚拟(JVM)运行时数据区. 在Java语言和虚拟机规范中对运行时数据区进行 ...

  2. 从头开始学习->JVM(八):运行时数据区(下)

    前言 在上一篇文章中,我们了解到了JVM的运行时数据区,基本被划分了5个区域. 程序计数器(pc寄存器) java虚拟机栈 本地方法栈 java堆 方法区(永久代,元空间). 而上一篇文章中,我们详细 ...

  3. 【jvm系列-04】精通运行时数据区共享区域---堆

    JVM系列整体栏目 内容 链接地址 [一]初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 [二 ...

  4. JVM Runtime Data Area(运行时数据区中的堆/栈/方法区讲解)

    JVM的组成 JVM由4大部分组成:ClassLoader .Runtime Data Area .Execution Engine .Native Interface.我们这里重点讲得是Runtim ...

  5. java虚拟机之一内存运行时数据区域解释

    Java虚拟机管理的内存运行时数据区域解释 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启 ...

  6. JVM(类加载、运行时数据区、堆内存、方法区、本地接口、执行引擎和垃圾回收)java虚拟机(JVM)的超详细知识点

    JVM虚拟机 一.JVM的概述 1.为什么要学习JVM 2.虚拟机 3.JVM的作用 作用 特点 4.JVM的位置 5.JVM的分类 6.各个组成部分的用途 7.Java 代码的执行流程 8.JVM ...

  7. Java程序员必知必会之JVM运行时数据区

    JVM类加载概述 JVM垃圾回收概述 运行时数据区概述 程序计数器(Program Counter Register) 是一块较小的内存空间,可以看作是当前线程所执行字节码的行号指示器,指向下一个将要 ...

  8. Java -----JVM运行时数据区

    一.JVM体系结构 想要了解运行时数据区,先关注一下JVM的体系结构,知道数据区在JVM的整体位置和作用. 二.JVM运行时数据区 1.程序计数器 一块较小的内存空间,它是当前线程所执行的字节码的行号 ...

  9. JVM学习笔记之-运行时数据区概述及线程概述,程序计数器(PC寄存器),虚拟机栈(栈,局部变量表,操作数栈,动态连接,方法调用,方法返回地址等),本地方法接口,本地方法栈

    运行时数据区概述及线程概述 内存是非常重要的系统资源,是硬盘和CPU的中间仓库及桥梁,承载着操作系统和应用程序的实时运行.JVM内存布局规定了Java在运行过程中内存申请.分配.管理的策略,保证了JV ...

最新文章

  1. gentoo emerge安装软件
  2. db2存储结构换Oracle,DB2中实现Oracle的功能
  3. hbase 修改表名_hbase修改表名 - 张欢19933的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. OpenCV:分离图像和视频的RGB通道
  5. 《那些年啊,那些事——一个程序员的奋斗史》——86
  6. CSS3自定义浏览器滚动条样式
  7. 使用Typora上传博客到博客园
  8. JWT—JSON Web Token - 理解JWT网络间应用用户安全认证交互设计
  9. 10、configparser模块
  10. Excel的模板导出+背景水印
  11. 百词斩 计算机英语词汇表,单词之美四级-英语词汇百词斩拓海有道金山词霸典...
  12. Arch-008ArchLinux安装steam
  13. 第六章:纯策略纳什均衡
  14. 【AIOT】Python语音处理
  15. 使用SDL2_mixer库播放MP3音乐
  16. 进程创建-终止-等待-替换
  17. BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛(10)题解
  18. Fiddler4下载安装和火狐搭配使用
  19. 【SGD深入理解】vanilia SGDmomentum SGD
  20. Dbeaver报错:The server time zone value ‘etd‘ is unrecognized

热门文章

  1. 时控开关c语言程序,德力西KG316T时控开关调整和设定时间操作方法说明
  2. wParam与 lParam
  3. 如何区分安装的oracle数据库是客户端还是服务器端?
  4. QMdiSubWindow
  5. 【教程】unet图像分割检测墙体裂缝检测_瑕疵检测python含代码
  6. Pytorch的model.train() model.eval() torch.no_grad() 为什么测试的时候不调用loss.backward()计算梯度还要关闭梯度
  7. 【STM32技巧】ADC模拟量采集的几种用法
  8. python最难的地方_最令人头疼的 Python 问题
  9. 7-172 元宵花灯
  10. 详解运放及其补偿技术