IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JVM内存结构之本地方法栈、堆 -> 正文阅读

[Java知识库]JVM内存结构之本地方法栈、堆

3. 本地方法栈

在这里插入图片描述

本地方法栈是java虚拟机在调用一些本地方法时需要给这些本地方法提供的内存空间,本地方法是指那些不是由java代码编写的方法,因为
我们的java代码是有一定的限制的,它有的时候不能直接跟我们的操作系统底层打交道,所以就需要一些用c或c++编写的本地方法来与操作系统更
底层的api来打交道,java代码可以间接地通过本地方法来调用到底层的一些功能,那这些本地方法运行的时候使用的内存就叫做本地方法栈,
那这样的本地方法多不多呢?答案是非常的多,不管是一些java的基础类库里还是在执行引擎里,它们都会去调用这些本地方法

在这里插入图片描述

Object类里面的clone()方法是做一个对象的克隆,可以看到它的方法声明就是native,这种native的方法它是没有方法实现的,
它的方法实现都是由c或c++语言编写的,我们的Java代码通过本地方法接口间接地调用真正的c和c++的它的实现,这样的方法很多,
比如Object类里的hashCode()方法就是本地方法,Object类的notify()方法和notifyAll()方法也都是本地方法,Object类
的wait()方法也是本地方法

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本地方法栈的作用就是给本地方法的运行提供一个内存空间

4. 堆

在这里插入图片描述

前面我们讲的程序计数器、虚拟机栈、本地方法栈它们有一个共同的特点,它们
都是线程私有的,而从我们现在开始讲解的堆以及后面的方法区它们可以看成是
线程共享的区域,接下来我们看一下堆的定义。

4.1 定义

Heap 堆

  • 通过new关键字,创建的对象都会使用堆的内存

特点

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

    以前我们说的虚拟机栈它中的一些局部变量那都是线程私有的,只要你的局部变量
    不逃逸出方法的作用范围,它就是线程安全的。
    但是我们的堆不一样,因为堆中的对象一般来讲都是需要考虑线程安全问题的,因为它们都是线程共享的,当然也会有例外,后面
    我们会讲到
    
  • 垃圾回收机制

    堆中不再被引用的对象就会当成垃圾进行一个回收以释放空闲的内存,不至于内存被创建的对象给撑爆。
    

4.2 堆内存溢出

// 运行下面这段代码
import java.util.ArrayList;
import java.util.List;

/**
 * 演示堆内存溢出 java.lang.OutOfMemoryError: Java heap space
 * -Xmx8m
 */
public class Demo06 {
    public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "hello";
            while (true){
                list.add(a);
                a = a + a;
                i++;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println(i);
        }
    }
}

结果如下:

在这里插入图片描述

那我们分析一下这个案例,看看它为什么产生了堆内存溢出。
a字符串不断递增,而a一直追加到list集合的尾部,不断地把hello字符串对象加入到list集合当中,而list集合它的生存范围从它被声明
开始,一直到catch块前面,它都是一个有效范围,所以它不能被垃圾回收掉,也就是程序还没有达到catch之前,那么它一直都是在它的有效
范围内,所以它就一直有效,而它里面的字符串对象由于被追加到了list集合的内部,所以这些字符串对象相当于有人在使用它们,它们也不能
被垃圾回收,所以随着字符串对象越来越多、越来越多,它就会把我们的堆空间占满了,这就是我们堆空间溢出的一个分析。
接下来我们讲一个参数: -Xmx8m
这个参数可以控制堆空间的最大值,现在我们将堆空间设置为8m

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

当我们设置堆空间为8m后,我们再次运行上面的程序

在这里插入图片描述

有的时候内存非常大的时候,它可能不太容易暴露这个内存溢出的问题,也许随着时间的累计,它最终会导致你的内存溢出,但是由于你的内存
比较大,可能你运行了很短的一段时间,你觉得它没问题,因为很短的时间堆内存仍然足够,所以排查这种堆内存溢出的问题,大家最好把你的
堆内存设的稍微小一些,这样可能尽早的暴露出可能引起的堆内存溢出的问题。

4.3 堆内存诊断

这里介绍一些堆内存诊断相关的工具,这些命令可以直接在命令行窗口上敲

  1. jps工具
  • 查看当前系统中有哪些java进程,并且把他们的进程编号显示出来。

拿到java进程的id以后,我们就可以通过jmap工具查看这个java进程堆内存的使用情况

  1. jmap工具
  • 查看堆内存的使用情况 jmap -heap 进程id
jmap只能查看某个时刻它的堆内存的占用情况,如果想要做一个连续的监测,去查看随着时间的流逝堆内存的占用情况的话,我们就得用一个
功能更复杂的jconsole工具来进行监测。
  1. jconsole工具
  • 图形界面的
jconsole工具是图形界面的,而前两种工具都是命令行的方式,另外jconsole是一个多功能的监测工具,它不仅可以监测堆内存的占用,
它还可以监测线程、cpu这些都可以通过jconsole来监测,而且它也能实现这种连续的监测,下面我们通过一些案例具体来看看这几个工具
它们的使用。

我们看一下这个案例:

/**
 * 演示堆内存
 */
public class Demo07 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("1...");
        // 这里让线程睡30s是为了让我们有时间输入命令
        Thread.sleep(30000);
        // new 10M 的数据
        byte[] array = new byte[1024 * 1024 * 10];  // 10 MB,   1K   1M   10M
        // 输出2...说明已经new了10M的数据
        System.out.println("2...");
        // 这里让线程睡30s是为了让我们有时间输入命令
        Thread.sleep(30000);
        array = null;
        System.gc();
        // 输出3...说明已经执行了垃圾回收
        System.out.println("3...");
        Thread.sleep(1000000L);

    }
}

首先,我们先把程序运行起来,然后使用jps工具查看我们运行的java程序的进程id

在这里插入图片描述

之后我们在程序输出1…的时候使用jmap -heap 线程id命令查看我们运行的java程序此时的堆内存使用情况

也就是 jmap -heap 110540命令

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

执行到2,也就是新数组10M在堆空间被分配了以后,我们再来监测一遍

在这里插入图片描述

在这里插入图片描述

我们再继续往下看,执行到3,也就是垃圾回收以后,我们再监测一遍

在这里插入图片描述

在这里插入图片描述

看完了jps和jmap工具的使用,下面我们来看一下jconsole工具的使用。

在命令行输入jconsole就可以出现jconsole工具的窗口

在这里插入图片描述

在这里插入图片描述

之后我们来动态监测一下java程序运行过程中的堆内存使用情况

首先我们来看一下,在输出1的时候,也就是程序刚开始运行还没有创建数组的时候,堆内存使用情况为二十几M

在这里插入图片描述

在程序输出2的时候此时已经新建了数组,此时堆内存的使用为四十几M,相较于输出1时的堆内存情况我们可以看到增长了十几M

在这里插入图片描述

最后在程序输出3的时候堆内存为6M多,这时我们已经进行过了垃圾回收,且此时由于数组引用为空,数组也被当成垃圾回收掉了

在这里插入图片描述

另外,jconsole窗口还可以查看内存的使用情况以及查看cpu的占用率
在这里插入图片描述

在这里插入图片描述

接下来我们再介绍一个案例,来学习jvisualvm

案例

  • 垃圾回收后,内存占用依然很高

我们运行下面的程序


import java.util.ArrayList;
import java.util.List;

/**
 * 演示查看对象个数 堆转储 dump(抓取内存快照)
 */
public class Demo08 {
    public static void main(String[] args) throws InterruptedException {
        List<Student> students = new ArrayList<>();
        for (int i = 0; i < 200; i++) {
            students.add(new Student());
        }
        Thread.sleep(1000000000L);
    }
}
class Student{
    private byte[] big = new byte[1024 * 1024];
}

首先我们通过jps工具来看看进程id,从下面的图中我们可以看到进程id是112088

在这里插入图片描述

使用jmap -heap 112088 来看看这个线程的内存使用情况

在这里插入图片描述

我们可以发现总共使用了200多M内存

在这里插入图片描述

接下来我们使用jconsole执行一次垃圾回收

jconsole工具的使用前面已经经过了,忘记的话可以去翻一下前面的知识啊

在这里插入图片描述

接下来我们再次使用jmap工具来看看内存使用情况,我们可以发现新生代内存确实被回收了不少,但是老年代却还是有很多

在这里插入图片描述

我们就很奇怪,为什么内存一直没有回收掉呢,是不是由于我们的编程失误导致一些对象始终被引用而无法释放它们的内存呢,接下来我们再介绍一个工具jvisualvm,它的意思是用可视化的方式来展示虚拟机内容

在这里插入图片描述

在这里插入图片描述

之后我们使用堆 Dump功能,它是抓取当前状态的快照,并对里面的内容进行详细的分析,这是jmap和jconsole所不具备的功能

在这里插入图片描述

之后我们查找前20个最占内存的对象

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

而且这些Student实例肯定是长期使用的,导致我们的垃圾回收没办法回收掉

接下来我们来看一下java源代码

在这里插入图片描述

实际环境下分析和排查的手段也是类似的,我们先通过堆 Dump这个功能把内存快照抓下来,抓下来以后我们分析对内存占用最大的那些对象,
就可以得出一些有用的结论,就可以发现到底是哪些对象占用的内存太大,那你再去分析和排查你的原始代码就可以了
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-05 21:35:51  更:2022-02-05 21:36:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:48:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码