概述
我们首先来认识一下 JVM 的运行时数据区域, 如果说 JVM 是一个人, 那么运行时数据区域就是这个人的骨架, 它支撑着 JVM 的运行, 所以我们先来学习一下运行时数据区域的分类和简单介绍.
分类
从所在区域角度上来说, 可以分为内部内存和外部内存, 其中内部的内存又包括了线程独占区和线程共享区.
在 JVM 内部, 从线程共享角度上来说, 又可以分为线程独占区和线程共享区.
线程独享区可以中包含以下三种数据区域:
程序计数器 (Program Counter Register)
虚拟机栈 (VM Stack)
本地方法栈 (Native Method Stack)
线程共享区中包含以下两种数据区域:
方法区 (Method Area)
堆 (Heap)
在 JVM 外部也就是本地内存中, 包含了直接内存和元数据 (Metadata), 在 JDK 1.8 中, 元数据就是我们之前的永久代 (持久代)
他们之间的区别是, JDK 7 在持久代中的常量池在 JDK 8 移到了堆内存中, 剩余部分移到了元数据中.
多线程的实现原理
上面我们把运行时的数据区域分为了线程独占区和线程共享区, 那么 Java 中的多线程是怎么实现的呢? 这可以帮助我们对于线程独占区和共享区有更深的理解.
在多个线程运行的时候, 其实是把 CPU 的使用时间分割成了无数个小份, 然后根据优先级去给这些线程分配时间, CPU 在这些小时间块中快速切换, 给用户的感受就是多线程同时在运行, 如下图:
通过这个图, 我们可以清晰的看出是如何达到多线程的效果 (其实在通信的时候也有同样的原理 -- 时分多路复用)
其实通俗一点来说, 线程的独占区主要是为了控制方法的正常运行, 而线程的共享区更类似于一个存储信息的仓库.
打个简单的比方, 现在有一个方法, 我们使用两个线程同时去调用这个方法, 属于该方法的信息就可以称之为独占区, 而类中的变量, 对象却可以被两个方法同时使用.
两种异常
在和 JVM 打交道的过程中, 我们经常会遇到两种错误: StackOverflowError 和 OutOfMemoryError,
StackOverflowError 异常出现在线程独占区的本地方法栈和虚拟机栈中, 而 OutOfMemoryError 会出现在除程序计数器外的所有区域.
公众号
原创文章, 才疏学浅, 如有不对之处, 万望告知!
来源: https://www.cnblogs.com/viyoung/p/11302673.html