jvm是什么?
1、java virtual machine java程序的运行环境 2、一次编写到处运行 3、自动内存管理,垃圾回收功能 4、java源代码-->编译器-->jvm可执行的java字节码(虚拟指令)-->jvm-->jvm中的解释器-->不同的机器(操作系统)可执行的机器码-->程序运行
常见的jvm?
HotSpot
jvm内存结构和执行引擎
内存结构:堆、栈、方法区、程序计数器、本地方法栈 执行引擎:解释器、即时编译器、垃圾回收
程序计数器
定义:当前线程所执行字节码的行号指示器;指向下一个将要执行的指令代码,由执行引擎来读取下一条指令 特点: 是线程私有的 不会存在内存溢出
栈
1、java虚拟机栈、本地方法栈,区别就是,Java 虚拟机栈为 JVM 执行 Java 方法服务,本地方法栈则为 JVM 使用到的 Native 方法服务。 2、Native 方法不是以 Java 语言实现的,而是以本地语言实现的(比如 C 或 C++)。个人理解Native 方法是与操作系统直接交互的。 3、虚拟机栈: a、每个线程运行时所需要的内存,称为虚拟机栈 b、每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存,栈帧中存储了局部变量表、操作数栈、动态连接和方法出口等信息。 c、局部变量表中存储了基本数据类型(boolean、byte、char、short、int、float、long、double)的局部变量(包括参数)、和对象的引用(String、数组、对象等),但是不存储对象的内容。 d、操作数栈,操作数栈是一个后进先出栈,操作数栈可以理解为栈帧中用于计算的临时数据存储区 e、每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法 f、异常: StackOverflowError:栈溢出错误,栈帧过多 OutOfMemoryError:内存不足,栈帧过大 g、栈中的变量如过逃离方法作用范围,发生了共享。则不是线程安全的
堆
1、堆内存是所有线程共享的,主要存放new关键字所创建的对象。 2、有垃圾回收机制 3、分为年轻代、老年代;年轻代又分为伊甸园和幸存区;幸存区又分为From Survivor空间和 To Survivor空间。 4、常用参数: -Xms:堆初始内存大小 -Xmx(MaxHeapSize):堆最大内存大小 -XX:NewSize(-Xns):年轻代内存初始大小 -XX:MaxNewSize(-Xmn):年轻代内存最大允许大小,也可以缩写 -XX:MaxTenuringThreshold=7:表示如果在幸存区移动多少次没有被垃圾回收,进入老年代 等等 5、检测工具:jps,jmap,jconsole
方法区
1、和堆一样是线程共享的空间。 2、储存:静态变量、常量、类信息(版本、方法代码、构造方法、字段(成员变量)等)、运行时常量池 3、方法区在jvm开始时创建。 4、jdk1.8使用元空间metaSpace实现方法区,1.6,1.7用永久代实现方法区,元空间不在jvm中,而是使用本地内存 5、常量池: 字面量(常量) final修饰的常量 基本数据类型的值 字符串 符号引用 类和接口的全限定名 方法名和描述符 字段名和描述符 6、运行时常量池: 在java程序运行期间产生的新的常量,这些常量放在运行时常量池中 类加载后,常量池中的常量将会在运行时常量池中存放 这里所说的常量包括:基本类型的包装类(包装类不包括浮点型,整型只包括-128到127之间)和String(也可以通过String.intern方法将String放入常量池中) 7、HotSpot中用StringTable来做为字符串常量池。本质用HashSet.实现。它只存储String实例的引用,而不存储String对象内容
直接内存
定义: 1、直接内存 并不是jvm虚拟机内存的一部分,而是操作系统内存 2、使用DirectByteBuffer对象来操作直接内存,避免了java堆和native内存的直接复制,提高了性能 回收机制: 1、不能使用jvm回收机制回收直接内存,jvm垃圾回收只能回收DirectByteBuffer对象。 2、使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法 3、ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存



