内存结构笔记 1

内存结构笔记 1

0、 程序计数器
  • Program Counter Register 程序计数器(寄存器)
  • 作用:记住下一条jvm指令的执行地址
  • 是线程私有的
  • CPU会为每个线程分配时间片,当前线程的时间片使用完以后,CPU就会去执行另一个线程中的代码
  • 程序计数器是每个线程所私有的,当另一个线程的时间片用完,又返回来执行当前线程的代码时,通过程序计数器可以知道应该执行哪一句指令
  • 不会存在内存溢出
一、栈内存溢出
  • 栈内存溢出:java.lang.StackOverflowError

    • 栈帧过多导致栈内存溢出:如没有终止条件的方法递归调用等

    • 栈帧过大导致栈内存溢出
      在这里插入图片描述

二、线程运行诊断

CPU占用高

  • top定位哪个进程对cpu的占用过高
  • ps H -eo pid,tid,%cpu | grep 进程id :用ps命令进一步定位是哪个线程引起的cpu占用过高(可以得到十进制的线程id)
  • jstack 进程id
    可以根据线程id(此时的线程id为十六进制,在匹配时需要将上一步得到的十进制的换算为十六进制) 找到有问题的线程,进一步定位到问题代码的源码行号

在这里插入图片描述

三、本地方法栈

在java虚拟机调用一些本地方法时需要给本地方法提供的内存空间

  • 本地方法:由于java有限制,不可以直接与操作系统底层交互,所以需要一些用c/c++编写的本地方法与操作系统底层的API交互,java可以间接的通过本地方法来调用底层功能
  • 举例:Object的clone()、hashCode()、notify()、notifyAll()、wait()等

在这里插入图片描述

四、 堆内存溢出

堆内存溢出:java.lang.OutofMemoryError :java heap space.

  • 可以通过参数-Xmx来控制程序堆的大小
五、堆内存诊断

jps工具:查看当前系统中有哪些java进程

在这里插入图片描述

jmap工具:查看某一时刻堆内存占用情况

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

jconsole工具:图形界面的,多功能的监测工具,可以连续监测

在这里插入图片描述

jvisualvm工具

在这里插入图片描述

查看占用内存最大的对象:ArrayList

在这里插入图片描述

ArrayList中的元素Student对象中包含的big属性占用1M内存,共有200个元素,占用200M内存

在这里插入图片描述

在这里插入图片描述

6、方法区定义

  • 所有java虚拟机线程的共享区域
  • 存储类的结构的相关信息,如运行时常量池、成员变量、方法数据、成员方法和构造器的代码等
  • 方法区在虚拟机启动时创建,其逻辑上是堆的一个组成部分,但在实现时不同的JVM厂商可能会有不同的实现

在这里插入图片描述

  • 常量池:常量池,就是一张,存储在*.class字节码文件中。虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
  • 运行时常量池:常量池是*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址

在这里插入图片描述

在这里插入图片描述

7、StringTable
  • 常量池中的字符串仅是符号,第一次用到时才变为对象。

  • 利用串池的机制,来避免重复创建字符串对象

    package cn.itcast.jvm.t1.stringtable;
    
    // StringTable [ "a", "b" ,"ab" ]  hashtable 结构,不能扩容
    public class Demo1_22 {
        // 常量池中的信息,都会被加载到运行时常量池中, 这时 a b ab 都是常量池中的符号,还没有变为 java 字符串对象
        // ldc #2 会把 a 符号变为 "a" 字符串对象
        // ldc #3 会把 b 符号变为 "b" 字符串对象
        // ldc #4 会把 ab 符号变为 "ab" 字符串对象
    
        public static void main(String[] args) {
            String s1 = "a"; // 懒惰的, 运行到此行才会创建字符串对象放入串池
            String s2 = "b";
            String s3 = "ab";
            String s4 = s1 + s2; // new StringBuilder().append("a").append("b").toString()  new String("ab")
            String s5 = "a" + "b";  // javac 在编译期间的优化,结果已经在编译期确定为ab
    
            System.out.println(s3 == s4);//false
            System.out.println(s3 == s5);//true
        }
    }
    
    
  • 对于字符串变量拼接String s4 = s1 + s2;:原理是 StringBuilder (1.8)

    • 其过程为:new StringBuilder().append("a").append("b").toString() ,即`new String(“ab”),其应当存储在堆中,而不是常量池
  • 对于字符常量拼接String s5 = "a" + "b"; :原理是编译期优化

    • javac 在编译期间的优化,结果已经在编译期确定"ab",因此会直接找到常量池中的值

    面试题

    package cn.itcast.jvm.t1.stringtable;
    
    public class Demo1_21 {
    
        public static void main(String[] args) {
            String s1 = "a";
            String s2 = "b";
            String s3 = "a" + "b"; // ab
            String s4 = s1 + s2;   // new String("ab")
            String s5 = "ab";
            String s6 = s4.intern();
    
    // 问
            System.out.println(s3 == s4); // false
            System.out.println(s3 == s5); // true
            System.out.println(s3 == s6); // true
    
            String x2 = new String("c") + new String("d"); // new String("cd")
            String x1 = "cd";
            x2.intern();
    
    // 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢//调换位置后:true//jdk1.6:false
            System.out.println(x1 == x2);//false
        }
    }
    
    
    • jdk1.6时,StringTable是常量池的一部分,随常量池存储在永久代中;jdk1.7/jdk1.8时StringTable从永久代转移到了堆中。
    • 永久代内存回收效率很低,只有Full GC时才会触发永久代的垃圾回收,而Full GC只有在整个老年代的空间不足时才会触发,时机较晚。而StringTable使用频繁,其中存储着大量字符串常量,若其回收效率不高就会占用大量内存,导致永久代内存不足。因此jdk1.7 / jdk1.8开始将StringTable从永久代转移到了堆中,只需要Minor GC就会对用不到的字符串进行堆垃圾回收,减轻了字符串对内存的占用。

    StringTable调优
    调整 -XX:StringTableSize=桶个数
    StringTable是由HashTable实现的,所以可以适当增加HashTable桶的个数,来减少字符串放入串池所需要的时间
    考虑将字符串对象是否入池
    若字符串对象很多且大量重复,可以考虑使用intern方法将字符串入池,减少重复对象

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!关于学习数据结构的C语言笔记,我可以给你一些基本的指导和概念。数据结构是计算机科学中非常重要的一门课程,它涉及存储和组织数据的方法。C语言是一种常用的编程语言,很适合用于实现各种数据结构。 下面是一些数据结构的基本概念,你可以在学习笔记中包含它们: 1. 数组(Array):一种线性数据结构,可以存储相同类型的元素。在C语言中,数组是通过索引访问的。 2. 链表(Linked List):也是一种线性数据结构,但不需要连续的内存空间。链表由节点组成,每个节点包含数据和指向下一个节点的指针。 3. 栈(Stack):一种后进先出(LIFO)的数据结构,类似于装满物品的箱子。在C语言中,可以使用数组或链表来实现栈。 4. 队列(Queue):一种先进先出(FIFO)的数据结构,类似于排队等候的队伍。同样可以使用数组或链表来实现队列。 5. 树(Tree):一种非线性数据结构,由节点和边组成。每个节点可以有多个子节点。二叉树是一种特殊的树结构,每个节点最多有两个子节点。 6. 图(Graph):另一种非线性数据结构,由节点和边组成。图可以用来表示各种实际问题,如社交网络和地图。 这只是数据结构中的一些基本概念,还有其他更高级的数据结构,如堆、哈希表和二叉搜索树等。在学习笔记中,你可以介绍每个数据结构的定义、操作以及适合使用它们的场景。 希望这些信息对你有所帮助!如果你有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值