JVM - 运行时数据区域

这篇具有很好参考价值的文章主要介绍了JVM - 运行时数据区域。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

程序计数器

并发情况下,会发生线程之间的上下文切换,当 线程1 的CPU时间片用完后,需要程序计数器记录 线程1 的下一条JVM指令的地址,等下一次 线程1 继续运行的时,才能从正确的位置开始继续执行

程序计数器是线程私有的 , 既 一个线程计数器 记录一个 线程 的指令位置

而且程序计数器是运行时数据区域唯一一个不存在内存溢出的区域

线程是什么?实际上可以理解为线程就是一个栈

线程调用方法 就是复制方法入栈的过程

方法入栈后就会形成栈帧

比如下面的一段代码

public class JvmDemo {
    public static void main(String[] args) {
        System.out.println("开始");
        func();
        System.out.println("结束");
    }  
    public static void func(){
    }   
}

执行该程序会创建一个主线程,然后main方法入栈,示意图如下

JVM - 运行时数据区域,JVM,jvm,java
接着mian方法执行到 func(); ,就会复制一份 func 方法入栈,如下

JVM - 运行时数据区域,JVM,jvm,java
func方法执行完后出栈,如下

JVM - 运行时数据区域,JVM,jvm,java
最后mian方法再出栈

我们说线程可以简单的认为就是栈,所以也很明显,栈是线程私有的

栈的容量有限,如果我们不断调用方法入栈,就会导致栈溢出 ( 比如递归时没有递归出口 )

栈分为 虚拟机栈本地方法栈

可以简单理解为 :
-入栈的方法由 java 语言编写 的为虚拟机栈
-入栈的方法由 C语言编写 的为本地方法栈

Object类中有很多本地方法,比如反射中用到的 public final native Class<?> getClass(); ,添加了native 关键字,使用C语言编写,为了能直接对接操作系统

关于栈的几个问题:

  1. 垃圾回收是否涉及栈内存? 不涉及 ,因为栈帧执行完就会自动出栈,无需垃圾回收
  2. 栈内存是否分配越大越好吗?错误 ,物理内存大小一定,栈内存越大,能同时纯在的栈就会越少,既 线程数会越少
  3. 方法内的局部变量是否是线程安全的? 是线程安全的,线程调用方法是复制方法入栈,所以每个线程都有自己的方法副本,也就有了自己的局部变量副本,所以在操作时,不会受到其他线程的干扰

堆 – 存储对象实例

比如下面代码

public class JvmDemo {
    public static void main(String[] args) {
        Person person = new Person();
    }
}

class Person{}

其在内存中的模型如下
JVM - 运行时数据区域,JVM,jvm,java
person引用存在main方法的栈帧中,而person实例对象存在于堆区中

堆区是所有线程共享的 ,比如

public class JvmDemo {
    public static void main(String[] args) {
        Person person = new Person();
        Thread thread01=new Thread(()->{
            Person person01 = new Person();
        });
        thread01.start();
    }
}

class Person{}

则内存模型如下,为了突出重点,省略 thread01 引用和实例对象 在内存中的展示,以及 thread01.start(); 的调用过程
JVM - 运行时数据区域,JVM,jvm,java
堆的内存有限,不能无限创建对象实例,否者会堆内存溢出

因此JVM存在堆区的垃圾回收机制,清除垃圾对象,垃圾对象 可以简单定义为没有引用指向的实例对象

比如

Person person = new Person;
person = new Person;

此时就没有引用指向第一个new出来的对象,那么它就会被垃圾回收

存在堆区中的对象实例是线程间共享的,对象中的 全局变量 需要考虑线程安全问题

比如

public class JvmDemo {
    public static void main(String[] args) throws InterruptedException {
        Person person = new Person();
        Thread thread01=new Thread(()->{
            for (int i=0;i<100000;i++){
                person.money++;
            }
        });
        thread01.start();
        for (int i=0;i<100000;i++){
            person.money++;
        }
        thread01.join();
        System.out.println(person.money);
    }
}
class Person{
    public int money=0;
}

输出的结果不一定是200000
JVM - 运行时数据区域,JVM,jvm,java

方法区

方法区 – 存储 类信息静态变量、方法

在 jdk 1.8之前,方法区存在于JVM内存中,其实现方法被称为 永久代;jdk 1.8及之后,方法区从JVM内存移出到本地内存,其实现方法被称为 元空间

方法区是线程共享的,因此多个线程修改同一个类的静态变量的时候同样存在线程安全问题,比如

public class JvmDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread01=new Thread(()->{
            for (int i=0;i<100000;i++){
                Person.money++;
            }
        });
        thread01.start();
        for (int i=0;i<100000;i++){
            Person.money++;
        }
        thread01.join();
        System.out.println(Person.money);
    }
}
class Person{
    public static int money=0;
}

输出结果同样不一定是200000,此处建议先学习一下什么是静态变量

方法区同样存在内存溢出的问题

知识延申 – 字符串常量池

JVM中还有一个特殊又重要的区域,就是 字符串常量池(StringTable),可以参考我的另外一篇博客

【Java 基础】你真的会用 String 吗?文章来源地址https://www.toymoban.com/news/detail-605367.html

到了这里,关于JVM - 运行时数据区域的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM运行时数据区——堆内的区域分布

    1.堆内的区域分布 堆是运行时数据区 最大 的一块区域, 主要用来存放对象 ,堆是所有 线程公用 的,在JVM 启动时就被创建 ,堆的 空间是可以调整 的,是GC(垃圾回收)的 重点区域 。 堆的内存空间分区:新生代+老年代 新生代又分为Eden(伊甸园)和Survivor(幸存者)区。  

    2024年02月16日
    浏览(35)
  • 【jvm系列-05】精通运行时数据区共享区域---方法区

    JVM系列整体栏目 内容 链接地址 【一】初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的类加载子系统以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈 https

    2023年04月09日
    浏览(26)
  • 【Jvm】运行时数据区域(Runtime Data Area)原理及应用场景

    Jvm由 4个部分 组成,分为2个子系统和2个组件 ,2个子系统为 Class loader(类装载)、Execution engine(执行引擎) ;2个组件为 Runtime Data Area(运行时数据区)、Native Interface(本地接口) 。 Class loader(类加载器) :根据给定的全限定名类名(如:Java.lang.Object)来装载class文件到Runtime data area中的

    2024年02月20日
    浏览(35)
  • JVM运行时区域——对象创建内存分配过程

            新创建的对象 , 都存放在伊甸园区域 ,当垃圾回收时,将伊甸园区域的垃圾数据销毁,然后将存活的对象转移到幸存者0区域,之后创建的新的对象还是存放在伊甸园区域,等到再次垃圾回收后,将伊甸园区域和幸存者0区域中存活的对象一起转移到幸存者1区域中

    2024年02月15日
    浏览(37)
  • JVM | Java内存区域

    以上笔记基于JavaGuide整理 JDK 1.8: 线程私有 的:程序计数器,虚拟机栈,本地方法栈 线程共享 的:堆,方法区(元空间),直接内存 (非运行时数据区的一部分) 程序计数器有两个作用: 字节码解释器通过改变程序计数器来依次读取指令,从而 实现代码的流程控制 ,如:顺

    2024年02月08日
    浏览(68)
  • JVM——Java 内存区域详解

    如果没有特殊说明,都是针对的是 HotSpot 虚拟机。 基本问题 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 拓展问题 String 类和常量池 8 种基本

    2024年02月13日
    浏览(33)
  • 【Java虚拟机学习1】JVM运行时数据区

    我们知道Java程序是运行在JVM(Java虚拟机)上的,Java程序运行时会占用一定的内存,在虚拟机自动管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出的问题,看起来由虚拟机管理内存一切都很美好。不过,也正式因为Java程

    2024年02月16日
    浏览(31)
  • JVM篇--Java内存区域高频面试题

    首先我们要知道java堆空间的产生过程: 即当通过java命令启动java进程的时候,就会为它分配内存,而分配内存的一部分就会用于创建堆空间,而当程序中创建对象的时候 就会从堆空间来分配内存,所以堆空间存放的主要是对象和数组; 而GC 其实说白了就是java虚拟机回收对象

    2024年02月01日
    浏览(41)
  • 深入理解 JVM 之——Java 内存区域与溢出异常

    更好的阅读体验 huge{color{red}{更好的阅读体验}} 更好的阅读体验 本篇为深入理解 Java 虚拟机第二章内容,推荐在学习前先掌握基础的 Linux 操作、编译原理、计算机组成原理等计算机基础以及扎实的 C/C++ 功底。 该系列的 GitHub 仓库:https://github.com/Doge2077/learn-jvm Java 虚拟机在

    2024年02月09日
    浏览(55)
  • 区分什么是Java内存模型(JMM)和 JVM运行时数据区

    Java的内存区域和内存模型是不一样的东西,内存区域是指 JVM 运行时将数据分区域存储,强调对内存空间的划分 。 而内存模型(Java Memory Model,简称 JMM )是 定义了线程和主内存之间的抽象关系,即 JMM 定义了 JVM 在计算机内存(RAM)中的工作方式 ,如果我们要想深入了解Java并

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包