运行时数据区
《Java虚拟机规范》:Java虚拟机所管理的内存包括:堆、方法区、虚拟机栈、本地方法栈、程序计数器。
Java堆
被所有线程共享的一块内存区域,在虚拟机启动时创建。用于存放对象实例和数组。也是垃圾收集器管理的区域(也叫GC堆)。为了更好的回收、分配内存,Java堆可能划分出多个线程私有的分配缓冲区(TLAB)。
堆大小可以通过参数-Xmx(最大堆大小)和-Xms(初始大小)扩展。如果堆中没有内存完成实例分配,并且堆已无法再扩展,则会抛出OutOfMemoryError异常。
方法区
线程共享区域,用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。JDK1.8之前也叫“永久代”。
JDK1.7前,运行时常量池存放在方法区中,逻辑包含字符串常量池,
JDK1.7 将字符串常量池、静态变量移到堆中。
JDK1.8之后废弃永久代,改用元空间(metaspace)代替,采用本地内存实现。
参数-XX:MaxPermSize指定永久代上限大小。方法区如果无法满足内存分配需求,抛出OutOfMemoryError异常。
虚拟机栈
线程私有,生命周期与线程相同。描述的是Java方法执行的线程内存模型:每个方法被执行的时候,虚拟机会创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等。
局部变量表:编译期可知的各种虚拟机基本数据类型、对象引用(局部变量表)、returnAddress类型。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈容量可以动态扩展,当栈无法申请到足够内存会抛出OutOfMemoryError异常。
本地方法栈
与虚拟机栈作用类似,区别是本地方法栈是为虚拟机使用到的本地方法服务。
程序计数器
Program Counter Register,当前线程所执行的字节码的行号指示器。概念模型中,字节码解释器工作需要通过这个计数器选取下一条执行的字节码指令。
线程私有:多线程是通过线程轮流切换、分配处理器执行时间的方式工作,为了线程切换后能恢复到正确的执行位置,程序器必须是线程独有的,互不影响。唯一一块没有规定任何OutOfMemoryError情况的区域。
直接内存
在JDK 1.4中新加入了NIO(New Input/Output) 类, 引入了一种基于通道(Channel) 与缓冲区
(Buffer) 的I/O方式, 它可以使用Native函数库直接分配堆外内存, 然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。 这样能在一些场景中显著提高性能, 因为避免了在Java堆和Native堆中来回复制数据。
面试官:说说什么是 Java 内存模型(JMM)?_爱笑的架构师-CSDN博客
2. 对象的创建?内存布局?对象的访问定位方式?当Java虚拟机遇到一条字节码new指令时, 首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用, 并且检查这个符号引用代表的类是否已被加载、 解析和初始化过。 如果没有, 那必须先执行相应的类加载过程。类加载检查通过后,虚拟机将为新生对象分配内存。所需的内存大小在类加载阶段就可以确定。为对象分配空间实际上就是把一块确定大小的内存块从堆中划分出来。
分配方式:
指针碰撞(Bump The Pointer):假设堆内存是绝对规整的,所有被使用的内存都被放在一边,中间有一个指针作为分界点指示,那分配内存只需要把指针向空闲区域移动一块对象大小的距离。
空闲列表:假设内存不是规整的,已使用未使用内存相互交错,则虚拟机会维护一个列表,记录哪些内存是空闲的,从列表中找到一块足够大的空间划分给实例。
Java 堆是否规整是由锁采用的垃圾收集器是否带有空间压缩整理的能力决定的。
对象在堆内存中的布局分为三个部分:对象头、实例数据、对其填充
对象头
包括Mark Word和类型指针两部分。
Mark Word用于存储对象自身的运行时数据(哈希码,GC分代年龄、锁状态标记、线程持有锁、偏向线程ID、偏向数据戳等)。类型指针即对象指向它的类型元数据的指针,通过这个指针确定该对象是哪个类的实例。
HotSpot虚拟机对象头Mark Word
实例数据
对象真正存储的有效信息,在代码里定义的各种类型的字段内容。
对其填充
起到占位符作业。HotSpot自动内存管理要求对象起始地址必须是8字节整数倍。
Java程序是通过栈上的Reference数据来操作堆上的具体对象。主流访问方式:句柄和直接指针。
通过句柄访问:
直接指针访问:
3.垃圾回收策略?垃圾回收算法?垃圾回收器? 4.类加载机制?双亲委派模型?Java虚拟机把描述类的数据从Class文件加载到内存, 并对数据进行校验、 转换解析和初始化, 最终形成可以被虚拟机直接使用的Java类型, 这个过程被称作虚拟机的类加载机制。
类加载过程:加载、验证、准备、解析、初始化、使用、卸载
设计模式用过吗?用过哪些设计模式?怎么用的?单例模式:一个类只有一个实例对象,单例对象由单例类自行创建,对外提供一个全局访问点。数据库的连接池、多线程中的线程池、Web 应用的配置对象、系统中的缓存等常被设计成单例。避免造成资源浪费或者不一致。
单例模式(单例设计模式)详解
常见实现方式:
饿汉式:类一旦加载就创建了单例对象。
懒汉式:第一次调用getlnstance才去创建这个单例。
双重检测:
volatile:
反射破坏单例:
工厂模式:
策略模式:



