2024年末java面试第一弹
-
- 1、SQL优化的15种常用方法包括:
- 2、64 位 JVM 中,int 的长度是多数?
- 3、32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?
- 4、JRE、JDK、JVM 及 JIT 之间有什么不同?
- 5、解释 Java 堆空间及 GC?
- 6、你能保证 GC 执行吗?
- 7、怎么获取 Java 程序使用的内存?堆使用的百分比?
- 8、Java 中堆和栈有什么区别?
- 9、描述一下 JVM 加载 class 文件的原理机制
- 10、GC 是什么?为什么要有 GC?
- 11、JVM 类加载机制
- 12、栈
- 13、本地方法栈
- 14、程序计数器
- 15、堆
- 16、方法区
- 17、堆和栈的区别
- 18、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
- 19、Java对象创建过程
- 20、简述Java的对象结构
- 21、如何判断对象可以被回收
- 22、JVM的永久代中会发生垃圾回收么
- 23、垃圾收集算法
- 24、调优命令有哪些?
- 25、调优工具
- 26、你知道哪些JVM性能调优
- 27、什么是线程池?为什么使用线程池?
- 28、Java中有哪些线程池实现?
- 29、ThreadPoolExecutor的核心参数是什么?
- 30、线程池的工作原理是什么?
- 31、线程池的拒绝策略有哪些?
- 32、线程池中的线程是如何复用的?
- 33、如何选择线程池的核心线程数和最大线程数?
- 34、什么是线程池的预热机制?
- 35、线程池的优点是什么?
- 36、线程池的缺点是什么?
- 37、线程池中的线程是如何管理的?
- 38、什么是任务队列?线程池中的任务队列有什么作用?
- 39、线程池中的线程是如何执行任务的?
- 40、有哪些线程池的最佳实践?
- 41、线程池中的任务可以返回结果吗?如何实现带返回值的任务执行?
- 42、如何处理线程池中的异常?
- 43、什么是线程工厂(Thread Factory)?线程池中的线程工厂有什么作用?
- 44、线程池和单线程执行有什么区别?
- 45、线程池的资源泄漏问题如何避免?
- 46、在多线程环境下,如何确保线程池中的任务按照特定顺序执行?
- 47、MySQL存储引擎及比较?
- 48、存储引擎索引结构
- 49、简述事务及其特性,mysql 如何实现事务?
- 50、事务的隔离级别有哪些?
- 51、什么是脏读,幻读,不可重复读,可重复读?
- 52、Mysql高可用方案有哪些?
- 53、简述触发器,函数,视图,存储过程
- 54、mysql常见的函数
- 55、char 和varchar的区别?
- 56、mysql-explain执行计划
- 57、1000w条数据, 使用limit分页, 为什么越往后越慢
- 58、读写分离
- 59、什么是读写分离?
- 60、数据库分组架构解决什么问题?
- 61、sql半同步复制原理
- 62、sql注入攻击原理,代码层防止sql注入
- 63、慢日志
- 64、乐观锁与悲观锁
- 65、表锁
- 66、行锁
- 67、在普通索引中,什么情况下会引发表锁
- 68、聚集索引和非聚集索引
- 69、sql断点调试怎么开启?
- 70、mysql为什么选择B+树?
- 71、B树
- 72、B+树
- 73、当mysql执行一条sql时,内部流程
- 74、synchronized 的原理
- 75、什么是 IoC?
- 76、IoC 解决了什么问题?
- 77、什么是 AOP?
- 78、AOP 为什么叫面向切面编程?
- 79、AOP 常见的通知类型有哪些?
- 80、AOP 解决了什么问题?
- 81、AOP 的应用场景有哪些?
- 82、AOP 实现方式有哪些?
- 83、JAVA中的集合
- 84、序列化
1、SQL优化的15种常用方法包括:
避免使用SELECT * :选择具体的字段而不是所有字段,可以节省资源并减少网络开销,同时避免回表查询,提高查询效率。
使用合适字段类型:选择合适的字段类型,例如使用数值类型代替字符串,可以减少存储空间并加快比较速度。
使用覆盖索引:确保索引包含查询所需的所有列,减少回表查询。
合理使用JOIN:避免不必要的表连接,特别是多表连接时,确保连接条件足够严格。
使用子查询和临时表:对于复杂的查询,先通过子查询或创建临时表来简化主查询。
分页查询优化:使用主键范围查询等方式优化分页,避免使用大的OFFSET值。
使用EXISTS代替IN:在某些情况下,EXISTS比IN更高效,特别是在子查询返回大量数据时。
使用UNION ALL代替UNION:UNION ALL不进行去重操作,效率更高。
避免使用OR条件:OR条件可能导致索引失效,尽量使用UNION ALL替代。
控制索引的数量:过多的索引会增加数据插入、删除和更新的成本,定期审查索引使用情况,删除不必要的索引。
批量操作:批量插入、删除和更新操作比单条操作更高效。
避免在WHERE子句中使用NULL:尽量使用具体的值代替NULL,以避免全表扫描。
使用LIMIT:避免返回不必要的数据,提升查询效率。
避免在索引列上使用函数:在索引列上使用函数会导致索引失效。
在GROUP BY前进行条件过滤:先进行条件过滤再执行GROUP BY操作,以提高效率。
2、64 位 JVM 中,int 的长度是多数?
Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。
3、32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?
理论上说上 32 位的 JVM 堆内存可以到达 2^32, 即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5GB,Solaris 大约3GB。64 位 JVM 允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。
4、JRE、JDK、JVM 及 JIT 之间有什么不同?
JRE 代表 Java 运行时(Java run-time),是运行 Java 引用所必须的。JDK 代表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java编译器,它也包含 JRE。JVM 代表 Java 虚拟机(Java virtual machine),它的责任是运行 Java 应用。JIT 代表即时编译(Just In Time compilation),当代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。
5、解释 Java 堆空间及 GC?
当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个进程,回收无效对象的内存用于将来的分配。
6、你能保证 GC 执行吗?
不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC的执行。
7、怎么获取 Java 程序使用的内存?堆使用的百分比?
可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory()方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
8、Java 中堆和栈有什么区别?
JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。
9、描述一下 JVM 加载 class 文件的原理机制
JVM 中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java 中的类加载器是一个重要的 Java 运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于 Java 的跨平台性,经过编译的 Java 源程序并不是一个可执行程序,而是一个或多个类文件。当 Java 程序需要使用某个类时,JVM 会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class 文件中的数据读入到内存中,通常是创建一个字节数组读入.class 文件,然后产生与所加载类对应
的 Class 对象。
加载完成后,Class 对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后 JVM 对
类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader 的子类)。
从 Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM 更好的保证了 Java 平台的安全性,在该机制中,JVM 自带的Bootstrap 是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM 不会向 Java 程序提供对 Bootstrap 的引用。下面是关于几个类
加载器的说明:
Bootstrap:一般用本地代码实现,负责加载 JVM 基础核心类库(rt.jar);
Extension:从 java.ext.dirs 系统属性所指定的目录中加载类库,它的父加载器是 Bootstrap;
System:又叫应用类加载器,其父类是 Extension。它是应用最广泛的类加载器。它从环境变量 classpath 或者系统属性
java.class.path 所指定的目录中记载类,是用户自定义加载器的默认父加载器。
10、GC 是什么?为什么要有 GC?
GC 是垃 圾收 集的 意思 ,内存 处理 是编 程人 员容 易出 现问 题的 地方 ,忘记 或者 错误的内 存回 收会 导致 程序 或系 统的 不稳 定甚 至崩 溃, Java 提供 的 GC 功能 可以 自动监测 对象 是否 超过 作用 域从 而达 到自 动回 收内 存的 目的 ,Java 语言 没有 提供 释放已分 配内存的 显示 操作 方法 。Java 程序 员不 用担 心内 存管 理, 因为 垃圾 收集 器会自动 进行 管理 。要 请求 垃圾 收集 ,可 以调 用下 面的 方法 之一 :System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以 屏蔽 掉显 示的 垃圾 回收 调用 。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
11、JVM 类加载机制
JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化
加载 加载是类加载过程中的一个阶段, 这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对象, 作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个 Class 文件获取,这里既可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。
验证 这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。 准备 准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。
解析 解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。
初始化 初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。
JVM内存模型
线程独占:栈,本地方法栈,程序计数器线程共享:堆,方法区
12、栈
又称方法栈,线程私有的,线程执行方法是都会创建一个栈阵,用来存储局部变量表,操作栈,动态链接,方法 出口等信息.调用方法时执行入栈,方法返回式执行出栈.
13、本地方法栈
与栈类似,也是用来保存执行方法的信息.执行Java方法是使用栈,执行Native方法时使用本地方法栈.
14、程序计数器
保存着当前线程执行的字节码位置,每个线程工作时都有独立的计数器,只为执行Java方法服务,执行Native方法时,程序计数器为空.
15、堆
JVM内存管理最大的一块,对被线程共享,目的是存放对象的实例,几乎所欲的对象实例都会放在这里,当堆没有可用空间时,会抛出OOM异常.根 据对象的存活周期不同,JVM把对象进行分代管理,由垃圾回收器进行垃圾的回收管理
16、方法区
又称非堆区,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器优化后的代码等数据.1.7的永久代和1.8的元空间都是方法区的一种 实现。
17、堆和栈的区别
栈是运行时单位,代表着逻辑,内含基本数据类型和堆中对象引用,所在区域连续,没有碎片;堆是存储单位,代表着数据,可被多个栈共享(包括成员中基本数据类型、引用和引用对象),所在区域不连续,会有碎片。
- 功能不同
栈内存用来存储局部变量和方法调用,而堆内存用来存储Java中的对象。无论是成员变量,局部变量, 还是类变量,它们指向的对象都存储在堆内存中。 - 共享性不同
栈内存是线程私有的。
堆内存是所有线程共有的。 - 异常错误不同
如果栈内存或者堆内存不足都会抛出异常。
栈空间不足:java.lang.StackOverFlowError。堆空间不足:java.lang.OutOfMemoryError。 - 空间大小
栈的空间大小远远小于堆的
18、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的 指令长度和其他特性。
19、Java对象创建过程
JVM遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引用。然后加载这个类(类加载过程在 后边讲) 2. 为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程缓冲分配(TLAB)”
将除对象头外的对象内存空间初始化为0
对对象头进行必要设置
20、简述Java的对象结构
Java对象由三个部分组成:对象头、实例数据、对齐填充。
对象头由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、线程持有的锁、偏向线程ID(一般占32/64 bit)。第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。
实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的) 对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐 )
21、如何判断对象可以被回收
判断对象是否存活一般有两种方式:
引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。
可达性分析(Reachability Analysis&#x