一、内存结构

Ⅰ、什么是JVM

  • JVMJava Virtual MachineJAVA程序运行时的环境。
  • 优势:1、一次代码编写,到处运行;2、自动内存管理,垃圾回收机制;3、数组越界检查。


Ⅱ、内存结构

1、整体架构

2、程序计数器

  • 作用:用于保存JVM中下一条所要执行的指令的地址;
  • 特点:a、线程私有;b、不会存在溢出;

3、虚拟机栈

  • 定义:Java虚拟机栈描述的是Java方法执行的内存模型,是每个线程独有的;
  • 每个方法执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
  • 每个线程当前只能有一个活动栈帧,对应于当前执行的方法。

3.1 问题辨析

  • 1、垃圾回收机制是否涉及到栈内存?
    • 不涉及。因为虚拟机栈是由一个个栈帧组成的,待方法执行完毕之后,对应的栈帧就会弹栈,所以无需垃圾回收机制;
  • 2、栈内存分配越大越好?
  • 不一定。在物理内存一定的情况下,如果栈内存分配的越大,当前线程可执行的递归次数相应变大,但是同时存在的线程数目会减少。
  • 3、方法内的局部变量是否线程安全?
    • 不一定。如果线程的局部变量没有逃离方法的作用范围,是安全的;
    • 但是如果线程的局部变量引用了对象,并且逃离了方法的作用范围,是需要考虑线程安全的。

3.2 栈内存溢出

  • Java.lang.stackOverflowError:栈内存溢出;
  • 原因:1、虚拟机栈中,栈帧过多;2、每个栈帧所占用过大;

4、本地方法栈

  • 一些带有native关键字的方法就是需要JAVA去调用本地的C或者C++方法,因为JAVA有时候没法直接和操作系统底层交互,所以需要用到本地方法

5、堆

  • Java中所有对象的实例化都是在堆中分配内存;
  • 所有线程共享,堆内存中的对象需要考虑线程安全问题;
  • 有垃圾回收机制。

6、方法区

  • 用于存储已经被虚拟机加载的类型的信息、常量、静态变量、即时编译器编译后的代码缓存数据等;


6.1 常量池与运行时常量池

  • 常量池就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型和字面量信息;
  • 运行时常量池:运行时常量池是方法区的一部分。常量池是被记录在Class文件中,当类被加载后,这部分内容将被加载到运行时常量池。

6.2 串池(String Table)

  • 串池的位置:在JVM1.6中串池位于常量池中,而对于JVM1.8,串池被分配到堆内存当中。
  • 利用串池的机制,可以避免重复创建字符串对象;
  • 字符串变量的拼接底层是利用了StringBuilder
  • 字符串常量拼接的是在编译阶段编译器进行了优化;
  • 可以使用intern方法,主动将串池中还没有的字符串对象放入串池中;
    • 1.8中调用字符串对象的intern方法,会将该字符串尝试放入到串池中。如果串池中没有该字符串对象,则放入成功;如果串池中存在该字符串对象,放入失败,返回串池中的字符串对象;
    • 而在1.6中,会将字符串尝试放入串池中,如果有不会放入,返回串池中的对象;如果没有,会把该对象拷贝一份,放入串池中,并返回串池中的对象。

6.3 String Table调优

  • 由于StringTable是由HashTable实现的,所以可以适当的增加其中的桶个数,来减少哈希计算时产生的碰撞次数。

7. 直接内存

  • 属于操作系统,常见于NIO操作时用于数据缓冲区;
  • 分配回收成本高,但是读写性能好;
  • 不受JVM内存回收管理。

7.1 文件读写流程

  • 使用了DirectBuffer


  • 直接内存是操作系统和Java代码都可以访问的一块区域,无需将代码从系统内存复制到Java堆内存,从而提高了读写效率。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容