美文网首页
09-本地方法栈和堆内存

09-本地方法栈和堆内存

作者: OpenCoder | 来源:发表于2021-08-12 11:46 被阅读0次

一.本地方法栈

image

Nativemethodstack(本地方法栈):保存native方法进入区域的地址

对于一个运行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,但不止如此,它还可以做任何它想做的事情。

任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。

这幅图展示了JAVA虚拟机内部线程运行的全景图。一个线程可能在整个生命周期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法栈之间跳转。

image

该线程首先调用了两个Java方法,而第二个Java方法又调用了一个本地方法,这样导致虚拟机使用了一个本地方法栈。假设这是一个C语言栈,其间有两个C函数,第一个C函数被第二个Java方法当做本地方法调用,而这个C函数又调用了第二个C函数。之后第二个C函数又通过本地方法接口回调了一个Java方法(第三个Java方法),最终这个Java方法又调用了一个Java方法(它成为图中的当前方法)。

二.堆

[图片上传失败...(image-4a4b99-1628739980681)]-1623394077737_20210719143743.png)

2.1概念

Heap 堆

  • 通过 new 关键字创建对象都会使用堆内存
  • 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。它是 JVM 管理的最大一块内存空间。

特点

  • 它是线程共享的,堆中对象都需要考虑线程安全的问题

    《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。所有的线程共享Java堆,在堆中还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)。

  • 有垃圾回收机制(后续在第二个系列:垃圾回收机制深入讲解)

说明:

当栈帧被执行的时候,里面有对象的创建,那么栈帧里面仅仅是保存对象名以及对应的地址值,真正的对象存储是分配在了堆内存:(全流程图)

image

2.2内存分配关系

  《Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都应当在运行时分配在堆上。(The heap is the run-time data area from which memory for all class instances and arrays is allocated)

要注意的是:“几乎”所有的对象实例都在这里分配内存——是从实际使用角度看的。因为还有一些对象是在栈上分配的。

数组和对象可能永远不会存储在栈上,因为栈帧中保存引用,这个引用指向对象或者数组在堆中的位置。

比如下面一段很简单的代码:
public class Demo2 {
    public static void main(String[] args) {
        Hello h1 = new Hello();
        Hello h2 = new Hello();
    }
}
class Hello{
}

在内存中的存放位置如下:

image

在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除,也就是触发了GC的时候,才会进行回收。如果堆中对象马上被回收,那么用户线程就会受到影响。

堆,是GC(Garbage Collection,垃圾收集器)执行垃圾回收的重点区域。

2.3设置堆内存大小与OOM

Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项"-Xmx"和"-Xms"来进行设置。

“-Xms"用于表示堆区的起始内存,等价于-XX:InitialHeapSize。

“-Xmx"用于表示堆区的最大内存,等价于-XX:MaxHeapSize。

一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时,将会抛出OutOfMemoryError异常。

通常会将-Xms和-Xmx两个参数配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小,从而提高性能

默认情况下:

初始内存大小:电脑物理内存大小/64。

最大内存大小:电脑物理内存大小/4。

可以通过如下代码进行查看:

/**
 * -Xms 用来设置堆空间(年轻代+老年代)的初始内存大小
 *  -X:是jvm运行参数
 *  ms:memory start
 * -Xmx:用来设置堆空间(年轻代+老年代)的最大内存大小
 */
public class Demo3 {
    public static void main(String[] args) {
        // 返回Java虚拟机中的堆内存总量
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        // 返回Java虚拟机试图使用的最大堆内存
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
        System.out.println("-Xms:" + initialMemory + "M");
        System.out.println("-Xmx:" + maxMemory + "M");
    }
}

运行结果:

-Xms:245M

-Xmx:3625M

相关文章

  • 09-本地方法栈和堆内存

    一.本地方法栈 Nativemethodstack(本地方法栈):保存native方法进入区域的地址 对于一个运行...

  • JVM相关笔记

    JVM内存模型 JVM主要由堆内存,方法区,程序计数器,虚拟机栈,本地方法栈组成,其中对堆内存和方法区是线程共有的...

  • Java内存模型探究

    一、内存模型 JVM的内存模型如下图所示,由堆、方法区、java栈、本地栈和程序计数器组成。 堆和方法区 是所有线...

  • JVM内存详解--堆和栈

    JVM内存组成结构 JVM栈由堆、栈、本地方法栈、方法区等部分组成 1)堆 所有通过new创建的对象的内存都在堆中...

  • 深入理解java虚拟机之jvm内存模型

    深入理解JVM—JVM内存模型 java的内存模型包括:本地方法区,java堆,Java虚拟机栈,本地方法栈,程序...

  • [安卓开发日记] 内存模型和GC

    一 、JAVA内存主要分5块:堆 - 方法区 - 程序计数器 - 本地方法栈 - 虚拟机栈 堆 和 方法区 这两块...

  • 2.2运行时数据区域

    Java虚拟机管理的内存包括几个运行时数据内存:程序计数器、虚拟机栈、本地方法栈、堆和方法区,其中方法区和堆是线程...

  • JVM - 内存结构

    JVM - 内存结构 方法区和堆是所有线程共享的内存区域,java栈、本地方法栈和程序计数器是运行时线程私有的内存...

  • jvm笔记

    jvm内存区域 程序计数器 虚拟机栈 本地方法栈 java的堆 方法区 java如何访问对象 垃圾回收和内存分配

  • Android 优化之-内存泄漏

    Java的内存结构 方法区和堆是所有线程共享的内存区域;而java栈、本地方法栈和程序计数区是妹个线程所私有的内存...

网友评论

      本文标题:09-本地方法栈和堆内存

      本文链接:https://www.haomeiwen.com/subject/myclbltx.html