JVM是什么?它的位置在哪?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

JVM位置:

java hmm Javahmm分别是什么_java

JVM的体系结构,类加载器结构图

java hmm Javahmm分别是什么_职场和发展_02


java hmm Javahmm分别是什么_职场和发展_03

什么是双亲委派机制?

Java提供了三种类加载器:

启动类加载器(BootstrapClassLoder)
扩展类加载器(ExtClassLoder)
应用程序类加载器(AppClassLoder)

以下是三种类加载器关系图:

java hmm Javahmm分别是什么_java_04


既然有这么多加载器,加载一个类时使用的是哪个类加载器?如果不同类加载器有同名类,以哪个为准,如何避免类名冲突?

这时就需要用到双亲委派机制。

双亲委派机制是指在收到加载请求时当前类(一般都是在应用程序类内)不会去加载这个类,而是把该类请求发送到向上一级加载类中进行比较,如果扩展类加载器没有.Class文件,继续向上比较,如果启动类加载器也没有.Class文件则会递归回来让应用程序类加载;这样做的好处就是:该机制主要是为了防止重复加载,保证了.class不能被篡改,即使篡改也不会被加载,保证了.Class的安全。

什么是沙箱安全机制?

在Java中将执行程序分成本地代码和远程代码两种,本地代码默认视为可信任的,而远程代码则被看作是不受信的。对于授信的本地代码,可以访问一切本地资源。而对于非授信的远程代码在早期的Java实现中,安全依赖于沙箱 (Sandbox) 机制。但如此严格的安全机制也给程序的功能扩展带来障碍,比如当用户希望远程代码访问本地系统的文件时候,就无法实现。因此在后续的 Java1.1 版本中,针对安全机制做了改进,增加了安全策略,允许用户指定代码对本地资源的访问权限。
将代码限定在虚拟机特定的运行范围内,严格限制代码对本地资源的访问,通过这样的措施来保证对代码有效的隔离,防止对本地系统造成破坏。
组成沙箱的基本组件:
字节码校验器(确保Java类文件遵循Java语言规范。这样可以帮助Java程序实现内存保护。但并不是所有的类文件都会经过字节码校验,比如核心类。)
类加载器(防止恶意代码去干涉善意的代码,守护了被信任的类库边界,将代码归入保护域,确定了代码可以进行哪些操作)
存取控制器(存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定)
安全管理器(是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。)
安全软件包(java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:

安全提供者
消息摘要
数字签名
加密鉴别

Native关键字

Native关键字在面试环节中相当重要,如果你是应届生并且熟悉该知识点的话会相当加分
首先我们要知道JNI是什么,JNI是Java Native Interface的缩写,JAVA本地调用。从jdk1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。看过JDK源代码的人肯定会注意到在源码里有很多标记成native的方法。这些个方法只有方法签名但是没有方法体。其实这些naive方法就是我们说的 java native interface。他提供了一个调用(invoke)的接口,然后用C或者C++去实现;
凡是带了Native关键字的方法,说明JAVA的作用范围已经达不到了,会去调用底层C语言的库。
过程:进入本地方法栈——JNI——>本地方法库
JNI(Java Native Interface)作用:扩展Java使用,融合不同的编程语言为Java所用。

Java诞生的时候C、C++横行,要要立足,必须要有调用C、C++的程序来突出优点。
在内存区域中专门开辟了一块标记区域:Native Method Stack,登记native方法

PC寄存器(程序计数器)

PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令

方法区(Method Area)

方法区(Method Area)与 Java 堆一样,是所有线程共享的内存区域,所有的字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间。
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。
方法区内存入的:static、final、Class、常量池。

什么是新生区(Eden)、幸存者区、老年区、永久存储区。

新生区:

类:诞生和成长的地方,甚至死亡;
伊甸园区:所有的对象都是在 伊甸园区 new出来的!

幸存者区:

当新生区对象不再被引用,垃圾回收之后,如果有存活对象会转移到幸存者区。

老年区

幸存者区经历过数次垃圾回收之后仍然存活下来的对象会被转移到老年区。

永久存储区

这个区域常驻内存,用来存放JDK自身携带的Class对象。如Interface元数据。存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收!关闭虚拟机就会释放这个区域的内存。

栈、堆

栈:先进后出。
栈内存主要负责程序的运行,生命周期和线程的同步,线程一旦结束栈内存就会释放,对于栈不存在垃圾回收问题,一旦线程结束,栈就会结束。
栈运行原理:栈帧
堆(heap)分为三个部分:新生区(eden)、老年区、永久存储区(JAVA8之后叫元空间)
新生区分为三个部分:伊甸园、幸存者0、幸存者1。(幸存者区是动态的)
GC垃圾回收主要针对新生区与老年区(GC轻回收针对新生区,GC重回收针对老年区)。
当新生区存储空间满,数据会存入老年区,当老年区存储空间满的时候则报错误:java.lang.OutOfMemoryError:Java heap space。
需求注意的是:幸存者区是动态的,幸存者区0和1的位置并不固定,这个后面会有说到。

堆内存调优

堆内存调优问题建议搜索视频学习

GC垃圾回收

JVM在进行GC时,并不是对这三个区域统一回收,大部分时候回收的都是新生代。
两种类:轻GC(普通的GC)重GC(全局GC)
GC三种算法:

标记压缩与清除算法
复制算法
引用计数器算法

引用计数器算法:会给每一个对象标记使用次数,使用次数为0则回收。
标记清除与标记压缩算法:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。但是回收之后会产生大量内存碎片浪费内存,所以配合标记压缩使用。
复制算法(伊甸与幸存区主要适用):当一个伊甸区对象经过GC之后仍然存活时,会被存放至form幸存区,to幸存区则会一直保持为空,如果被存入对象,则会复制到from幸存区,经历15次GC后form幸存区仍然有对象存活则会放入养老区。

(-XX:MaxTenuringThreshold=15)
复制算法的优点:没有内存碎片
缺点: 浪费内存空间

三种算法比较:

内存效率:复制算法>标记清除算法>标记压缩算法
内存整齐度:复制算法>标记压缩算法>标记清除算法
内存利用率:标记压缩算法=标记清除算法>复制算法

什么是JMM?有什么作用?

JMM就是Java内存模型。

作用:

1.缓存一致性协议,用于定义数据读写的规则。

2.解决共享对象可见性问题。(volilate)

JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在出内存中,每个线程都有一个私有的本地内存。

java hmm Javahmm分别是什么_java hmm_05