`

Java 内存的原型及工作原理

    博客分类:
  • JVM
阅读更多
一、java虚拟机内存原型

为什么JVM内存会如此设计呢:
目前大致的分为:堆、栈、方法区、程序计数器、直接内存
为什么会分这么多呢?
要想程序运行起来,需要不同的数据,不同的模型。如:线程运行时有线程的一些专有属性。
第二就是 为了 内存的回收,可以分别调优。给用户更大选择。
除了 程序计算器没有内存溢出外,每个区都会有内存溢出。(程序计算器所使用的内存太少了)
结合一些参数,及内存溢出的异常。
大致如下图所示:




寄存器:我们在程序中无法控制栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中堆:存放用new产生的数据静态域:存放在对象中用static定义的静态成员常量池:存放常量非RAM存储:硬盘等永久存储空间。

二、常量池(constant pool)

常量池指的是在编译期被确定,并被保存在已编译的。class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:

1、类和接口的全限定名;

2、字段的名称和描述符;

3、方法和名称和描述符。

虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的, 对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引 用。说到这里,对常量池中的字符串值的存储位置应该有一个比较明了的理解了。在程序执行的时候,常量池 会储存在Method Area,而不是堆中。

三、Java内存分配中的栈

栈的基本单位是帧(或栈帧):每当一个java线程运行的时候, java虚拟机会为该线程分配一个java栈。该线程在执行某个java方法的时候, 向java栈压入一个帧,这个帧用于存储参数、局部变量、操作数、中间运算结果等。当这个方法执行完的时候,帧会从栈中弹出。Java栈上的所有数据是私有的,其他线程都不能该线程的栈数据。在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

四、Java内存分配中的堆

java虚拟机中的堆用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动的垃圾回收机制来管理堆的内存。简单的说和栈相对,堆主要是用来存放java对象的,栈主要是用来存放对象引用的…在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。 引用变量就相当于是 为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。

引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是Java 比较占内存的原因。实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!

Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存 大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态 分配内存,存取速度较慢。

堆栈对比

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

int a=3; int b=3; 编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3.接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3.这样,就出现了a与b同时均指向3的情况。

这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响 到b的值。

要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

  • 大小: 30.5 KB
分享到:
评论

相关推荐

    深度剖析Java中的内存原型及工作原理

    1. **Java虚拟机内存原型**: - **寄存器**:虽然Java程序员无法直接控制,但Java虚拟机(JVM)可能会使用寄存器来优化性能,存储临时数据。 - **栈**:存储方法调用时的局部变量、基本类型和对象引用。栈内存的...

    详解JAVA 原型模式

    **工作原理** - 具体原型类需要实现`java.lang.Cloneable`接口,表明该类支持克隆操作。 - 实现`clone()`方法,通常需要调用`super.clone()`,但在某些情况下,可能需要更复杂的深拷贝逻辑。 - 当需要创建新对象时,...

    图解JS原型和原型链实现原理

    JS选择了不同于Java的路径,放弃了“类”的概念,转而采用基于原型的继承。 在JS中,构造函数起到了类似Java中类的作用。当使用`new`关键字创建对象时,实际上是在调用构造函数。每个构造函数都有一个`prototype`...

    java调用C语言编写的so库中的函数,java调用C语言编写的dll库中的函数

    总的来说,Java调用C语言编写的本地库需要理解JNI和JNA的工作原理,以及它们如何处理数据类型转换、参数传递和本地库的加载。通过这些技术,开发者可以充分利用C/C++的性能优势,同时享受Java的平台独立性和高级抽象...

    JAVA通过JNI调用C#dll的整个项目工程

    Java通过JNI调用C# DLL是一个跨平台、跨语言的技术实践,主要应用于需要利用Java的稳定性和C#的高性能...通过学习和实践这个工程,开发者可以进一步提升跨语言编程的能力,更好地理解和掌握JNI以及P/Invoke的工作原理。

    Java手机操作系统开发入门

    理解KVM的工作原理,包括内存管理、垃圾回收和性能优化,对于提高Java应用程序的运行效率非常重要。 六、UI设计 在手机操作系统中,用户界面是与用户交互的关键。学习如何使用MIDP提供的用户界面组件,如Form、...

    DELPHI 7 调用 JAVA 接口

    首先,理解Delphi 7调用Java接口的基础原理。这种通信通常依赖于Java的本地接口(JNI,Java Native Interface),它允许Java代码调用C/C++代码,而Delphi代码可以编译为C++兼容的库。因此,Delphi通过JNI桥接,可以...

    2018最新最全java高级工程师面试题

    2018年最全的Java高级工程师面试题集锦,包含了十几个文档,可以预见这些文档将涵盖JVM原理、并发编程、设计模式、数据结构与算法、Spring框架、数据库设计与优化、网络协议等多个领域。 1. **JVM(Java虚拟机)** ...

    Delphi10.3 中通过JNI调用 Java 函数

    首先,我们需要了解JNI的基本工作原理。JNI的核心是Java虚拟机(JVM)和本地方法接口。当Java代码调用本地方法时,JVM会通过JNI接口找到相应的本地代码,并执行该代码。在Delphi中,我们需要编写C或C++的动态链接库...

    原型模式(Prototype)

    在Java、C#等面向对象编程语言中,原型模式可以通过实现克隆接口或使用深拷贝和浅拷贝来实现。 ### 原理和组件 1. **原型(Prototype)**:这是模式的核心,它定义了接口用于复制自己。原型对象通常是具体的类,实现...

    高级Java经典面试题2019

    Java内存主要分为堆内存(Heap)、方法区(Method Area)、栈内存(Stack)、程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)。 #### Java堆的结构 Java堆是所有线程共享的一块内存...

    Java调用DLL源代码

    JNA的工作原理是通过映射Java方法到本地函数,使得Java代码能够调用C库中的函数。JNA的优势在于其简洁的API和无须编译的特性,使得开发过程更加高效。 使用JNA调用DLL的步骤如下: 1. **定义结构体和回调函数**:...

    用JAVA写的hsqldb面向对象的数据库

    通过阅读源代码和示例,你可以深入理解HSQDB的工作原理,以及如何在自己的项目中有效地利用它。 总之,HSQDB作为一个纯Java实现的轻量级数据库,其面向对象的设计和易用性使得它成为Java开发者的一个理想选择,特别...

    java面试——深圳-乐信-Java高级.zip

    在Java高级面试中,面试官通常会关注候选人在核心Java、多线程、集合框架、JVM内存管理、设计模式、数据库操作、网络编程、异常处理、IO流、Spring框架及其实现原理等方面的知识掌握程度。以下是根据这些关键点展开...

    JAVA白皮书(英文版)

    - **内存管理和垃圾回收**:深入探讨了Java中自动内存管理和垃圾回收机制的工作原理。 - **后台垃圾收集器**:详细介绍Java中后台垃圾收集器的工作方式和优势。 - **集成的线程同步**:阐述Java中线程同步的基本概念...

    Java面试题资料

    3. **JVM**:Java虚拟机的工作原理是面试中的热门话题。包括内存模型(堆、栈、方法区、本地方法栈等),垃圾收集机制(GC)及其算法,类加载机制(双亲委派模型)等。 4. **多线程**:Java并发编程是高级面试中的...

    Java面试宝典2018

    - `HashMap`的工作原理及内部实现机制。 - `TreeMap`的排序原理及其实现细节。 - **常见面试题**: - 如何选择合适的集合类型? - `HashMap`与`Hashtable`有何不同? - `ConcurrentHashMap`与`HashMap`的区别...

    360 java 研发笔试题

    5. Java内存模型(JMM)和线程通信。 四、IO与NIO Java的输入/输出(IO)和新IO(NIO)系统在处理数据传输方面起着关键作用: 1. 流的概念:字节流、字符流、缓冲流的层次结构。 2. 文件操作:创建、读写、复制...

    自己设计的Java计算机

    理解Java内存模型(JMM)对于确保正确性和并发性至关重要。 5. **运算符和逻辑**:实现基本的算术和逻辑运算,如加减乘除、位运算以及条件判断,是计算机功能的基础。 6. **控制流**:包括分支、循环等控制结构的...

    一份超级详细的Java面试题【大厂面试真题+Java学习指南+工作总结】.zip

    Java作为一款广泛应用的编程语言,其面试题涵盖了多个层面的知识,包括基础语法、数据结构与算法、多线程、集合框架、JVM内存管理、异常处理、IO/NIO、网络编程、设计模式以及框架应用等。下面将针对这些关键领域...

Global site tag (gtag.js) - Google Analytics