谈谈对Java的理解
- 平台无关性
- GC
- 语言特性(泛型,反射,lambda等)
- 面向对象
- 类库
- 异常处理
Java的平台无关性
Java源码首先被编译成字节码,再由不同平台的JVM进行解析,Java语言在不同的平台上运行时不需要重新编译,Java虚拟机在执行字节码的时候,把字节码转换成具体平台上的机器指令。
JVM如何加载.class文件
JVM架构图
- Class Loader:根据特定的格式,加载class文件到内存
- Execution Engine:对命令进行解析
- Native Interface:融合不同开发语言的原生库为Java所用
- Runtime Data Area:JVM内存空间模型
谈谈反射
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
ClassLoader的种类
- BootStrapClassLoader:C++编写,加载核心库java.*
- ExtClassLoader:java编写,加载扩展库javax.*
- AppClassLoader:java编写,加载程序所在目录(项目中的src)
- 自定义ClassLoader:java编写,定制化加载
双亲委派机制
当某个类加载器需要加载某个
.class
文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
作用
-
防止重复加载同一个
.class
。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。 -
保证核心
.class
不能被篡改。通过委托方式,不会去篡改核心.clas
,即使篡改也不会去加载,即使加载也不会是同一个.class
对象了。不同的加载器加载同一个.class
也不是同一个Class
对象。这样保证了Class
执行安全。
谈谈ClassLoader
ClassLoader在Java中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。它是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接、初始化等操作。
类加载的方式
- 隐式加载:new
- 显式加载:loadClass,forName
类的装载过程
loadClass和forName的区别
- 使用Class.forName(className)装载class会对相应的类进行初始化,即上图类的装载过程的第三步
- 使用ClassLoader.loadClass(className)装载class,则只会进行上图的第一步,不会进行链接
总结
一般情况下,这两个方法效果一样,都能装载Class。但如果程序依赖于Class是否被初始化,就必须用Class.forName(className)了。
如:jdbc中的Driver注册时只能用Class.forName(className)
因为,Driver在static块中会注册自己到java.sql.DriverManager。而static块就是在Class的初始化中被执行。所以这个地方就只能用Class.forName(className)。
JVM内存模型
线程私有部分:程序计数器、虚拟机栈、本地方法栈
-
程序计数器
- 当前线程所执行的字节码行号指示器(逻辑)(多线程时,上下文切换,依靠程序计数器来恢复正确的执行位置)
- 改变计数器的值来选取下一条需要执行的字节码指令
- 和线程是一对一的关系即“线程私有”
- 对Java方法计数,如果是Native方法则计数器值为Undefined
- 不会发生内存泄漏
-
虚拟机栈
- Java方法执行的内存模型
- 包含多个栈帧
- 局部变量表和操作数栈
- 局部变量表:包含方法执行过程中的所有变量
- 操作数栈:入栈、出栈、复制、交换、产生消费变量(用来执行加减乘除等操作)
-
本地方法栈
- 本地方法栈和java虚拟机栈十分相似,差别不过是java虚拟机栈是为了java虚拟机执行字节码所服务,而本地方法栈则是为了执行native方法所服务的,所以本地方法也是一个私有的内存区域,也是后进先出栈,作用是支撑native方法的调用,执行和退出与java虚拟机栈一样也会出现以上两种异常。
线程共享部分:共享部分为:MetaSpace(元空间),Java堆
-
元空间(MetaSpace)与永久代(PermGen)的区别:(用元空间代替永久代)
- 元空间使用的是本地内存,而永久代使用的是jvm的内存
- 字符串常量池存在永久代中,容易出现性能问题和内存溢出
- 类和方法的信息大小难以确定,给永久代的大小指定带来困难
- 永久代会为GC带来不必要的复杂性
-
Java堆(Heap),在虚拟机启动时创建
- 对象实例的分配区域(Java堆的唯一目的)
- GC管理的主要区域
JVM三大性能调优参数
- -Xss:规定了每个线程虚拟机栈的大小
- -Xms:堆的初始值
- -Xmx:堆能达到的最大值
Java内存模型中堆和栈的区别
-
联系:引用对象、数组时,栈里定义变量保存堆中目标的首地址
-
区别
- 管理方式:栈自动释放,堆需要GC
- 空间大小:栈比堆小
- 内存碎片相关:栈产生的碎片远小于堆
- 分配方式:栈支持静态和动态分配,而堆仅支持动态分配
- 效率:栈的效率比堆高