精华内容
下载资源
问答
  • java面试题及答案整理
    2022-04-29 19:01:54

    Java面试题及答案整理1500道(2021最新版)

    这是我收集的《Java 最常见的 1500道面试题》高级Java面试问题列表。这些问题主要来自 Java 核心部分 ,你可能知道这些棘手的 Java 问题的答案,或者觉得这些不足以挑战你的 Java 知识,但这些问题都是容易在各种 Java 面试中被问到的,而且包括我的朋友和同事在内的许多程序员都觉得很难回答。

    Java常见2021年最新面试题,附答案解析

    01、创建socket通讯的步骤?
    02、Java 中 sleep 方法和 wait 方法的区别?
    03、程序计数器(线程私有)
    04、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?
    05、迭代器 Iterator 是什么?
    06、线程的 sleep()方法和 yield()方法有什么区别?
    07、Java 中能创建 volatile 数组吗?
    08、java中equals方法的用法以及==的用法
    09、如何创建一个json对象?
    10、如何判断对象是否是垃圾?

    此处,仅展示前10道,查看更多40道…

    Java常见面试题及答案汇总,2021年最新版

    01、抽象工厂模式和原型模式之间的区别?
    02、在 Java 程序中怎么保证多线程的运行安全?
    03、volatile 修饰符的有过什么实践?
    04、Java中各种数据默认值
    05、说说Java 垃圾回收机制
    06、有没有可能两个不相等的对象有有相同的 hashcode?
    07、synchronized 和 Lock 有什么区别?
    08、什么是Vector
    09、对象的访问定位有哪几种方式?
    10、equals 和 == 的区别?#

    此处,仅展示前10道,查看更多40道…

    Java常见面试题,2021年及答案汇总

    01、什么是ThreadPoolExecutor?
    02、invokedynamic 指令是干什么的?
    03、synchronized、volatile、CAS 比较
    04、Iterator 怎么使用?有什么特点?
    05、被引用的对象就一定能存活吗?
    06、列出一些你常见的运行时异常?
    07、Servlet生命周期内调用的方法过程?
    08、阐述静态变量和实例变量的区别。
    09、类加载器双亲委派模型机制?
    10、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

    此处,仅展示前10道,查看更多40道…

    Java最新2021年面试题及答案,汇总版

    01、如何判断一个对象是否存活
    02、Int与integer的区别
    03、Servlet的生命周期?
    04、怎么唤醒一个阻塞的线程
    05、虚拟DOM的优劣如何?
    06、双亲委派模型是什么?
    07、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
    08、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
    09、JVM 出现 fullGC 很频繁,怎么去线上排查问题
    10、JVM 内存区域

    此处,仅展示前10道,查看更多40道…

    Java最新2021年面试题大汇总,附答案

    01、Parallel Old 收集器(多线程标记整理算法)
    02、对象分配内存是否线程安全?
    03、当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?
    04、Serial 与 Parallel GC 之间的不同之处?
    05、为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?
    06、redux异步中间件之间的优劣?
    07、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?
    08、Hibernate中Session的load和get方法的区别是什么?
    09、说一下堆内存中对象的分配的基本策略
    10、Java 中如何将字符串转换为整数?

    此处,仅展示前10道,查看更多40道…

    Java最新2021年面试题附答案解析,大汇总

    01、讲讲什么情况下会出现内存溢出,内存泄漏?
    02、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?
    03、线程与进程的区别?
    04、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?
    05、用代码演示三种代理
    06、stackoverflow错误,permgen space错误
    07、分代收集算法
    08、同步方法和同步块,哪个是更好的选择?
    09、Java 中的编译期常量是什么?使用它又什么风险?
    10、Java死锁以及如何避免?

    此处,仅展示前10道,查看更多40道…

    Java最新2021年面试题,高级面试题及附答案解析

    01、日期和时间:
    02、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
    03、依赖注入和工程模式之间有什么不同?
    04、Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)
    05、如何修改tomcat的端口号?
    06、Java有没有goto?
    07、Java 内存分配与回收策率以及 Minor GC 和 Major GC
    08、简述Hibernate常见优化策略。
    09、Statement与preparedStatement区别
    10、什么是DAO模式?

    此处,仅展示前10道,查看更多40道…

    Java最新基础面试题及答案整理

    01、String 属于基础的数据类型吗?
    02、如何实现对象克隆?
    03、Java最顶级的父类是哪个?
    04、如何通过反射创建对象?
    05、Java 中堆和栈有什么区别?
    06、volatile 能使得一个非原子操作变成原子操作吗?
    07、为什么选择使用框架而不是原生?
    08、你能写出一个正则表达式来判断一个字符串是否是一个数字吗?
    09、运行时栈帧包含哪些结构?
    10、什么是Java程序的主类?应用程序和小程序的主类有何不同?

    此处,仅展示前10道,查看更多40道…

    Java最新面试题2021年,常见面试题及答案汇总

    01、volatile 关键字的作用
    02、Java 中用到的线程调度算法是什么?
    03、简单描述一下(分代)垃圾回收的过程
    04、什么是可重入锁(ReentrantLock)?
    05、线程池有什么优点?
    06、你有哪些手段来排查 OOM 的问题?
    07、什么是线程异步?什么是线程同步?
    08、Java 中,受检查异常 和 不受检查异常的区别?
    09、OOP 中的 组合、聚合和关联有什么区别?
    10、Java网络编程有几种?

    此处,仅展示前10道,查看更多40道…

    Java最新面试题及答案整理,汇总版

    01、什么是Web Service(Web服务)
    02、内部类与静态内部类的区别?
    03、什么是代理模式
    04、32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?
    05、重排序实际执行的指令步骤
    06、invokedynamic指令是干什么的?
    07、如何选择单例创建方式
    08、Java集合的快速失败机制 “fail-fast”?
    09、如何实现字符串的反转及替换?
    10、Spring开发中的工厂设计模式

    此处,仅展示前10道,查看更多40道…

    Java最新面试题及答案附答案汇总

    01、js如何实现页面刷新呢?
    02、什么是线程池?
    03、如何实现 Array 和 List 之间的转换?
    04、普通类和抽象类有哪些区别?
    05、为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object 类里?
    06、遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?
    07、String str="i"与 String str=new String(“i”)一样吗?
    08、用过ConcurrentHashMap,讲一下他和HashTable的不同之处?
    09、线程的基本状态以及状态之间的关系?
    10、线程池中 submit() 和 execute() 方法有什么区别?

    此处,仅展示前10道,查看更多40道…

    Java最新面试题,2021年面试题及答案汇总

    01、你了解过哪些垃圾收集器?
    02、你是如何调用 wait() 方法的?使用 if 块还是循环?为什么?
    03、Java 中,如何计算两个日期之间的差距?
    04、JVM 类加载机制
    05、Sql中delete与truncate的区别
    06、poll() 方法和 remove() 方法的区别?
    07、一个线程运行时发生异常会怎样?
    08、游标的创建步骤?
    09、MyBatis中使用#和$书写占位符有什么区别?
    10、一个类文件中能否有多个类?有什么要求?

    此处,仅展示前10道,查看更多40道…

    Java最新面试题,常见面试题及答案汇总

    01、Java 8 为什么要将永久代(PermGen)替换为元空间(MetaSpace)呢?
    02、如何自定义线程线程池?
    03、类初始化的情况有哪些?
    04、Java里有哪些引用类型?
    05、JAVA8 与元数据
    06、引用计数法
    07、String str=”aaa”,与String str=new String(“aaa”)一样吗?
    08、Xml的java解析有几种方式?
    09、为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用?
    10、JVM新生代中为什么要分为Eden和Survivor?

    此处,仅展示前10道,查看更多40道…

    Java面试2021秋招面试问题,附答案

    01、在java中守护线程和本地线程区别?
    02、CMS分为哪几个阶段?
    03、抽象的关键字是什么?
    04、如何判断对象可以被回收
    05、如何通过反射调用对象的方法?
    06、如何进行单元测试
    07、什么情况下会发生栈内存溢出?
    08、什么是Hash算法
    09、什么是上下文切换?
    10、列举一些你知道的打破双亲委派机制的例子。为什么要打破?

    此处,仅展示前10道,查看更多40道…

    Java面试题及答案整理汇总,2021年最新版

    01、Thread 类中的 yield 方法有什么作用?
    02、如何在两个线程间共享数据?
    03、在一个静态方法内调用一个非静态成员为什么是非法的?
    04、设计模式分类
    05、为什么wait和notify方法要在同步块中调用?
    06、接口与抽象类有什么区别?
    07、我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗?
    08、说出几条 Java 中方法重载的最佳实践?
    09、垃圾收集算法
    10、Java 程序是怎样运行的?

    此处,仅展示前10道,查看更多40道…

    Java面试题及答案整理,2021年最新,汇总版

    01、如何写一段简单的死锁代码?
    02、栈帧都有哪些数据?
    03、float f=3.4;是否正确?
    04、形参与实参
    05、BIO、NIO、AIO 有什么区别?
    06、什么是自旋
    07、我们可以在 hashcode() 中使用随机数字吗?
    08、你所知道网络协议有那些?
    09、构造器Constructor是否可被override
    10、什么是双亲委派机制?

    此处,仅展示前10道,查看更多40道…

    Java面试题大全带答案,持续更新

    01、说一下Java对象的创建过程
    02、Java 中 LinkedHashMap 和 PriorityQueue 的区别是什么?
    03、ThreadPoolExecutor饱和策略有哪些?
    04、可达性分析
    05、成员变量与局部变量的区别有那些?
    06、HashMap 的长度为什么是2的幂次方
    07、谈谈JVM中,对类加载器的认识
    08、你对线程优先级的理解是什么?
    09、构造器(constructor)是否可被重写(override)?
    10、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?

    此处,仅展示前10道,查看更多40道…

    Java面试题大汇总,2021年附答案解析

    01、64 位 JVM 中,int 的长度是多数?
    02、线程的状态
    03、计算机网络有几层?
    04、模块化编程与热插拔
    05、我们能自己写一个容器类,然后使用 for-each 循环码?
    06、单例防止反射漏洞攻击
    07、工作中常用的 JVM 配置参数有哪些?
    08、面向对象的特征有哪些方面?
    09、是否了解连接池,使用连接池有什么好处?
    10、JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用

    此处,仅展示前10道,查看更多40道…

    更多相关内容
  • javaspring面试题链接以及java基础的一些资料Spring的三大核心思想:IOC(控制反转),DI(依赖注入),AOP(面向切面编程)。 (1)IOC(控制反转)  实现将组件间的关系从程序内部提到外部容器(spring的xml)...
  • 上一篇:Java经典面试题整理及答案详解(二) Java面试真题第三弹接住!相信通过前两节的学习,大家对于Java多少有些了解。学习Java建议还是多动手练习,很多时候你会发现想的和写出来运行的不是一回事儿,本节内容...
  • 2021最新、最全的Java面试题及答案,300页
  • Java中的异常处理机制的简单原理和应用,Java的接口和C++的虚类的相同和不同处等问题,适合初学者
  • 最常见的Java面试题及答案汇总(一)和Java高级面试题整理(附答案),值得拥有,真的值得拥有,真的值得拥有,真的值得拥有。
  • 发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~博主已将这些面试题整理到一个网站上,每天更新 Java 面试题,目前有 1万多道 Java 高频面试题。...

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~博主已将这些面试题整理到一个网站上,每天更新 Java 面试题,目前有 1万多道 Java 高频面试题。

    本套Java面试题大全,汇总了大量经典的Java程序员面试题以及答案,包含Java语言常见面试题、Java工程师高级面试题及一些大厂Java开发面试宝典

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    1、什么是ThreadPoolExecutor?

    ThreadPoolExecutor就是线程池

    ThreadPoolExecutor其实也是JAVA的一个类,我们一般通过Executors工厂类的方法,通过传入不同的参数,就可以构造出适用于不同应用场景下的ThreadPoolExecutor(线程池)

    构造参数图:

    构造参数参数介绍:

    corePoolSize 核心线程数量 maximumPoolSize 最大线程数量 keepAliveTime 线程保持时间,N个时间单位 unit 时间单位(比如秒,分) workQueue 阻塞队列 threadFactory 线程工厂 handler 线程池拒绝策略

    2、invokedynamic 指令是干什么的?

    Java 7 开始,新引入的字节码指令,可以实现一些动态类型语言的功能。Java 8 的 Lambda 表达式就是通过 invokedynamic 指令实现,使用方法句柄实现。

    3、synchronized、volatile、CAS 比较

    1、 synchronized 是悲观锁,属于抢占式,会引起其他线程阻塞。

    2、 volatile 提供多线程共享变量可见性和禁止指令重排序优化。

    3、 CAS 是基于冲突检测的乐观锁(非阻塞)

    4、Iterator 怎么使用?有什么特点?

    Iterator 使用代码如下:

    List<String> list = new ArrayList<>(); Iterator<String> it = list、iterator(); while(it、hasNext()){ String obj = it、next(); System、out、println(obj); }

    Iterator 的特点是只能单向遍历,但是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。

    5、被引用的对象就一定能存活吗?

    不一定,看 Reference 类型,弱引用在 GC 时会被回收,软引用在内存不足的时候,即 OOM 前会被回收,但如果没有在 Reference Chain 中的对象就一定会被回收。

    6、列出一些你常见的运行时异常?

    1、 ArithmeticException(算术异常)

    2、 ClassCastException (类转换异常)

    3、 IllegalArgumentException (非法参数异常)

    4、 IndexOutOfBoundsException (下标越界异常)

    5、 NullPointerException (空指针异常)

    6、 SecurityException (安全异常)

    7、Servlet生命周期内调用的方法过程?

    1、 Init()

    2、 Service()

    3、 doGet或者doPost

    4、 destroy

    8、阐述静态变量和实例变量的区别。

    静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

    补充:在Java开发中,上下文类和工具类中通常会有大量的静态成员。

    9、类加载器双亲委派模型机制?

    基本定义:

    双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器没有找到所需的类时,子加载器才会尝试去加载该类。

    双亲委派机制:

    1、 当 AppClassLoader 加载一个 class 时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器 ExtClassLoader 去完成。

    2、 当 ExtClassLoader 加载一个 class 时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给 BootStrapClassLoader 去完成。

    3、 如果 BootStrapClassLoader 加载失败,会使用 ExtClassLoader 来尝试加载;

    4、 若 ExtClassLoader 也加载失败,则会使用 AppClassLoader 来加载,如果 AppClassLoader 也加载失败,则会报出异常 ClassNotFoundException。

    如下图所示:

    双亲委派作用:

    1、 通过带有优先级的层级关可以避免类的重复加载;

    2、 保证 Java 程序安全稳定运行,Java 核心 API 定义类型不会被随意替换。

    10、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

    都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

    11、Parallel Old 收集器(多线程标记整理算法)

    Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多线程的标记-整理算法,在 JDK1.6才开始提供。

    在 JDK1.6 之前,新生代使用 ParallelScavenge 收集器只能搭配年老代的 Serial Old 收集器,只能保证新生代的吞吐量优先,无法保证整体的吞吐量, Parallel Old 正是为了在年老代同样提供吞吐量优先的垃圾收集器, 如果系统对吞吐量要求比较高,可以优先考虑新生代Parallel Scavenge和年老代 Parallel Old 收集器的搭配策略。

    12、对象分配内存是否线程安全?

    对象创建十分频繁,即使修改一个指针的位置在并发下也不是线程安全的,可能正给对象 A 分配内存,指针还没来得及修改,对象 B 又使用了指针来分配内存。

    解决方法:① CAS 加失败重试保证更新原子性。② 把内存分配按线程划分在不同空间,即每个线程在 Java 堆中预先分配一小块内存,叫做本地线程分配缓冲 TLAB,哪个线程要分配内存就在对应的 TLAB 分配,TLAB 用完了再进行同步。

    13、当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

    如果其他方法没有synchronized的话,其他线程是可以进入的。

    所以要开放一个线程安全的对象时,得保证每个方法都是线程安全的。

    14、Serial 与 Parallel GC 之间的不同之处?

    Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行。

    15、为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?

    因为Java所有类的都继承了Object,Java想让任何对象都可以作为锁,并且 wait(),notify()等方法用于等待对象的锁或者唤醒线程,在 Java 的线程中并没有可供任何对象使用的锁,所以任意对象调用方法一定定义在Object类中。

    有的人会说,既然是线程放弃对象锁,那也可以把wait()定义在Thread类里面啊,新定义的线程继承于Thread类,也不需要重新定义wait()方法的实现。然而,这样做有一个非常大的问题,一个线程完全可以持有很多锁,你一个线程放弃锁的时候,到底要放弃哪个锁?当然了,这种设计并不是不能实现,只是管理起来更加复杂。

    16、redux异步中间件之间的优劣?

    redux-thunk优点:

    1、 体积小: redux-thunk的实现方式很简单,只有不到20行代码

    2、 使用简单: redux-thunk没有引入像redux-saga或者redux-observable额外的范式,上手简单

    redux-thunk缺陷:

    1、 样板代码过多: 与redux本身一样,通常一个请求需要大量的代码,而且很多都是重复性质的

    2、 耦合严重: 异步操作与redux的action偶合在一起,不方便管理

    3、 功能孱弱: 有一些实际开发中常用的功能需要自己进行封装

    redux-saga优点:

    1、 异步解耦: 异步操作被被转移到单独 saga.js 中,不再是掺杂在 action.js 或 component.js 中

    2、 action摆脱thunk function: dispatch 的参数依然是一个纯粹的 action (FSA),而不是充满 “黑魔法” thunk function

    3、 异常处理: 受益于 generator function 的 saga 实现,代码异常/请求失败 都可以直接通过 try/catch 语法直接捕获处理

    4、 功能强大: redux-saga提供了大量的Saga 辅助函数和Effect 创建器供开发者使用,开发者无须封装或者简单封装即可使用

    5、 灵活: redux-saga可以将多个Saga可以串行/并行组合起来,形成一个非常实用的异步flow

    6、 易测试,提供了各种case的测试方案,包括mock task,分支覆盖等等

    redux-saga缺陷:

    1、 额外的学习成本: redux-saga不仅在使用难以理解的 generator function,而且有数十个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是rxjs和一整套思想

    2、 体积庞大: 体积略大,代码近2000行,min版25KB左右

    3、 功能过剩: 实际上并发控制等功能很难用到,但是我们依然需要引入这些代码

    4、 ts支持不友好: yield无法返回TS类型

    redux-observable优点:

    1、 功能最强: 由于背靠rxjs这个强大的响应式编程的库,借助rxjs的操作符,你可以几乎做任何你能想到的异步处理

    2、 背靠rxjs: 由于有rxjs的加持,如果你已经学习了rxjs,redux-observable的学习成本并不高,而且随着rxjs的升级redux-observable也会变得更强大

    redux-observable缺陷:

    1、 学习成本奇高: 如果你不会rxjs,则需要额外学习两个复杂的库

    2、 社区一般: redux-observable的下载量只有redux-saga的1/5,社区也不够活跃,在复杂异步流中间件这个层面redux-saga仍处于领导地位

    关于redux-saga与redux-observable的详细比较可见此链接

    最近在备战面试的过程中,整理一下面试题。大多数题目都是自己手敲的,网上也有很多这样的总结。自己感觉总是很乱,所以花了很久把自己觉得重要的东西总结了一下。

    17、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?

    双亲委托模型的重要用途是为了解决类载入过程中的安全性问题。

    1、 假设有一个开发者自己编写了一个名为java.lang.Object的类,想借此欺骗JVM。现在他要使用自定义ClassLoader来加载自己编写的java.lang.Object类。

    2、 然而幸运的是,双亲委托模型不会让他成功。因为JVM会优先在Bootstrap ClassLoader的路径下找到java.lang.Object类,并载入它

    Java的类加载是否一定遵循双亲委托模型?

    1、 在实际开发中,我们可以通过自定义ClassLoader,并重写父类的loadClass方法,来打破这一机制。

    2、 SPI就是打破了双亲委托机制的(SPI:服务提供发现)。

    18、Hibernate中Session的load和get方法的区别是什么?

    如果没有找到符合条件的记录,get方法返回null,load方法抛出异常。

    get方法直接返回实体类对象,load方法返回实体类对象的代理。

    在Hibernate 3之前,get方法只在一级缓存中进行数据查找,如果没有找到对应的数据则越过二级缓存,直接发出SQL语句完成数据读取;load方法则可以从二级缓存中获取数据;从Hibernate 3开始,get方法不再是对二级缓存只写不读,它也是可以访问二级缓存的。

    19、说一下堆内存中对象的分配的基本策略

    eden区、s0区、s1区都属于新生代,tentired 区属于老年代。大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden区->Survivor 区后对象的初始年龄变为1),当它的年龄增加到一定程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。另外,大对象和长期存活的对象会直接进入老年代。

    20、Java 中如何将字符串转换为整数?

    String s="123";

    int i;

    第一种方法:i=Integer.parseInt(s);

    第二种方法:i=Integer.valueOf(s).intValue();

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    21、Thread 类中的 yield 方法有什么作用?

    使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。

    当前线程到了就绪状态,那么接下来哪个线程会从就绪状态变成执行状态呢?可能是当前线程,也可能是其他线程,看系统的分配了。

    22、如何在两个线程间共享数据?

    在两个线程间共享变量即可实现共享。

    一般来说,共享变量要求变量本身是线程安全的,然后在线程内使用的时候,如果有对共享变量的复合操作,那么也得保证复合操作的线程安全性。

    23、在一个静态方法内调用一个非静态成员为什么是非法的?

    由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

    24、设计模式分类

    1、 创建型模式,共五种:工厂方法模式、抽象工厂模式单例模式、建造者模式、原型模式。

    2、 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

    3、 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    25、为什么wait和notify方法要在同步块中调用?

    Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。

    26、接口与抽象类有什么区别?

    1、 抽象类有构造方法,接口没有构造方法

    2、 抽象类只能单继承,接口可以多继承

    3、 抽象类可以有普通方法,接口中的所有方法都是抽象方法

    4、 接口的属性都是public static final修饰的,而抽象的不是

    27、我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗?

    不行,你不能在没有强制类型转换的前提下将一个 double 值赋值给 long 类型的变量,因为 double 类型的范围比 long 类型更广,所以必须要进行强制转换。

    28、说出几条 Java 中方法重载的最佳实践?

    下面有几条可以遵循的方法重载的最佳实践来避免造成自动装箱的混乱。

    a)不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参数。

    b)不要重载参数数量一致,而只是参数顺序不同的方法。

    c)如果重载的方法参数个数多于 5 个,采用可变参数。

    29、垃圾收集算法

    GC最基础的算法有三种:标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。

    标记 -清除算法

    “标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

    复制算法

    “复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

    标记-压缩算法

    标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

    分代收集算法

    “分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法

    30、Java 程序是怎样运行的?

    1. 首先通过 Javac 编译器将 .java 转为 JVM 可加载的 .class 字节码文件。
    2. Javac 是由 Java 编写的程序,编译过程可以分为:① 词法解析,通过空格分割出单词、操作符、控制符等信息,形成 token 信息流,传递给语法解析器。② 语法解析,把 token 信息流按照 Java 语法规则组装成语法树。③ 语义分析,检查关键字使用是否合理、类型是否匹配、作用域是否正确等。④ 字节码生成,将前面各个步骤的信息转换为字节码。
    3. 字节码必须通过类加载过程加载到 JVM 后才可以执行,执行有三种模式,解释执行、JIT 编译执行、JIT 编译与解释器混合执行(主流 JVM 默认执行的方式)。混合模式的优势在于解释器在启动时先解释执行,省去编译时间。
    4. 之后通过即时编译器 JIT 把字节码文件编译成本地机器码。
    5. Java 程序最初都是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会认定其为"热点代码",热点代码的检测主要有基于采样和基于计数器两种方式,为了提高热点代码的执行效率,虚拟机会把它们编译成本地机器码,尽可能对代码优化,在运行时完成这个任务的后端编译器被称为即时编译器。
    6. 还可以通过静态的提前编译器 AOT 直接把程序编译成与目标机器指令集相关的二进制代码。


    31、什么是“依赖注入”和“控制反转”?为什么有人使用?

    控制反转(IOC)是Spring框架的核心思想,用我自己的话说,就是你要做一件事,别自己可劲new了,你就说你要干啥,然后外包出去就好~

    依赖注入(DI) 在我浅薄的想法中,就是通过接口的引用和构造方法的表达,将一些事情整好了反过来传给需要用到的地方~

    32、ArrayList 和 LinkedList 的区别是什么?

    1、 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。

    2、 随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。

    3、 增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

    4、 内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

    5、 线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;

    6、 综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。

    7、 LinkedList 的双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

    33、观察者模式应用场景

    1、 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。事件多级触发场景。

    2、 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

    • 代码演示

    1、 定义抽象观察者,每一个实现该接口的实现类都是具体观察者。

    package com.lijie;
    
    //观察者的接口,用来存放观察者共有方法
    public interface Observer {
        // 观察者方法
        void update(int state);
    }

    2、 定义具体观察者

    package com.lijie;
    
    // 具体观察者
    public class ObserverImpl implements Observer {
    
        // 具体观察者的属性
        private int myState;
    
        public void update(int state) {
            myState=state;
            System.out.println("收到消息,myState值改为:"+state);
        }
    
        public int getMyState() {
            return myState;
        }
    }

    3、 定义主题。主题定义观察者数组,并实现增、删及通知操作。

    package com.lijie;
    
    import java.util.Vector;
    
    //定义主题,以及定义观察者数组,并实现增、删及通知操作。
    public class Subjecct {
        //观察者的存储集合,不推荐ArrayList,线程不安全,
        private Vector<Observer> list = new Vector<>();
    
        // 注册观察者方法
        public void registerObserver(Observer obs) {
            list.add(obs);
        }
        // 删除观察者方法
        public void removeObserver(Observer obs) {
            list.remove(obs);
        }
    
        // 通知所有的观察者更新
        public void notifyAllObserver(int state) {
            for (Observer observer : list) {
                observer.update(state);
            }
        }
    }

    4、 定义具体的,他继承继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多。

    package com.lijie;
    
    //具体主题
    public class RealObserver extends Subjecct {
        //被观察对象的属性
         private int state;
         public int getState(){
             return state;
         }
         public void  setState(int state){
             this.state=state;
             //主题对象(目标对象)值发生改变
             this.notifyAllObserver(state);
         }
    }

    5、 运行测试

    package com.lijie;
    
    public class Client {
    
        public static void main(String[] args) {
            // 目标对象
            RealObserver subject = new RealObserver();
            // 创建多个观察者
            ObserverImpl obs1 = new ObserverImpl();
            ObserverImpl obs2 = new ObserverImpl();
            ObserverImpl obs3 = new ObserverImpl();
            // 注册到观察队列中
            subject.registerObserver(obs1);
            subject.registerObserver(obs2);
            subject.registerObserver(obs3);
            // 改变State状态
            subject.setState(300);
            System.out.println("obs1观察者的MyState状态值为:"+obs1.getMyState());
            System.out.println("obs2观察者的MyState状态值为:"+obs2.getMyState());
            System.out.println("obs3观察者的MyState状态值为:"+obs3.getMyState());
            // 改变State状态
            subject.setState(400);
            System.out.println("obs1观察者的MyState状态值为:"+obs1.getMyState());
            System.out.println("obs2观察者的MyState状态值为:"+obs2.getMyState());
            System.out.println("obs3观察者的MyState状态值为:"+obs3.getMyState());
        }
    }

    34、Array与ArrayList有什么不一样?

    Array与ArrayList都是用来存储数据的集合。ArrayList底层是使用数组实现的,但是arrayList对数组进行了封装和功能扩展,拥有许多原生数组没有的一些功能。我们可以理解成ArrayList是Array的一个升级版。

    35、实例化数组后,能不能改变数组长度呢?

    不能,数组一旦实例化,它的长度就是固定的

    36、Java 中,Maven 和 ANT 有什么区别?

    虽然两者都是构建工具,都用于创建 Java 应用,但是 Maven 做的事情更多,在基于“约定优于配置”的概念下,提供标准的Java 项目结构,同时能为应用自动管理依赖(应用中所依赖的 JAR 文件),Maven 与 ANT 工具更多的不同之处请参见。

    1、 这就是所有的面试题,如此之多,是不是?我可以保证,如果你能回答列表中的所有问题,你就可以很轻松的应付任何核心 Java 或者高级 Java 面试。虽然,这里没有涵盖 Servlet、JSP、JSF、JPA,JMS,EJB 及其它 Java EE 技术,也没有包含主流的框架如 Spring MVC,Struts 2.0,Hibernate,也没有包含 SOAP 和 RESTful web service,但是这份列表对做 Java 开发的、准备应聘 Java web 开发职位的人还是同样有用的,因为所有的 Java 面试,开始的问题都是 Java 基础和 JDK API 相关的。如果你认为我这里有任何应该在这份列表中而被我遗漏了的 Java 流行的问题,你可以自由的给我建议。我的目的是从最近的面试中创建一份最新的、最优的 Java 面试问题列表。

    37、方法区的作用是什么?

    方法区用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

    JDK8 之前使用永久代实现方法区,容易内存溢出,因为永久代有 -XX:MaxPermSize 上限,即使不设置也有默认大小。JDK7 把放在永久代的字符串常量池、静态变量等移出,JDK8 中永久代完全废弃,改用在本地内存中实现的元空间代替,把 JDK 7 中永久代剩余内容(主要是类型信息)全部移到元空间。

    虚拟机规范对方法区的约束宽松,除和堆一样不需要连续内存和可选择固定大小/可扩展外,还可以不实现垃圾回收。垃圾回收在方法区出现较少,主要目标针对常量池和类型卸载。如果方法区无法满足新的内存分配需求,将抛出 OutOfMemoryError。

    38、接口和抽象类有什么区别?

    实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。 构造函数:抽象类可以有构造函数;接口不能有。 main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

    39、原型模式的应用场景

    1、 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。这时我们就可以通过原型拷贝避免这些消耗。

    2、 通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。

    3、 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。

    我们Spring框架中的多例就是使用原型

    40、ConcurrentHashMap 和 Hashtable 的区别?

    ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。

    底层数据结构

    JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;

    实现线程安全的方式

    1、 在JDK1.7的时候,ConcurrentHashMap(分段锁对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;

    2、 Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。

    两者的对比图

    1、 HashTable

    2、 JDK1.7的ConcurrentHashMap

    3、 JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点)

    ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,HashTable 考虑了同步的问题使用了synchronized 关键字,所以 HashTable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。


    41、线程和进程区别

    什么是线程和进程?

    进程

    一个在内存中运行的应用程序。 每个正在系统上运行的程序都是一个进程

    线程

    进程中的一个执行任务(控制单元), 它负责在程序里独立执行。

    一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据

    进程与线程的区别

    1、 根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

    2、 资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

    3、 包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

    4、 内存分配:同一进程的线程共享本进程的地址空间和资源,而进程与进程之间的地址空间和资源是相互独立的

    5、 影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃有可能导致整个进程都死掉。所以多进程要比多线程健壮。

    6、 执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

    42、老年代与标记复制算法

    而老年代因为每次只回收少量对象,因而采用 Mark-Compact 算法。

    1、 JAVA 虚拟机提到过的处于方法区的永生代(Permanet Generation), 它用来存储 class 类,常量,方法描述等。对永生代的回收主要包括废弃常量和无用的类。

    2、 对象的内存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目前存放对象的那一块),少数情况会直接分配到老生代。

    3、 当新生代的 Eden Space 和 From Space 空间不足时就会发生一次 GC,进行 GC 后, EdenSpace 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 FromSpace 进行清理。

    4、 如果 To Space 无法足够存储某个对象,则将这个对象存储到老生代。

    5、 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环。

    6、 当对象在 Survivor 去躲过一次 GC 后,其年龄就会+1。默认情况下年龄到达 15 的对象会被移到老生代中。

    43、什么是TreeMap

    1、 TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。

    2、 TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

    3、 TreeMap是线程非同步的。

    44、如何停止一个正在运行的线程?

    在java中有以下3种方法可以终止正在运行的线程:

    1、 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

    2、 使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。

    3、 使用interrupt方法中断线程。

    45、Java 中,编写多线程程序的时候你会遵循哪些最佳实践?

    这是我在写Java 并发程序的时候遵循的一些最佳实践:

    1、 给线程命名,这样可以帮助调试。

    2、 最小化同步的范围,而不是将整个方法同步,只对关键部分做同步。

    3、 如果可以,更偏向于使用 volatile 而不是 synchronized。

    4、 使用更高层次的并发工具,而不是使用 wait() 和 notify() 来实现线程间通信,如 BlockingQueue,CountDownLatch 及 Semeaphore。

    5、 优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。

    46、Java语言采用何种编码方案?有何特点?

    Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

    47、Java 中你怎样唤醒一个阻塞的线程?

    首先 ,wait()、notify() 方法是针对对象的,调用任意对象的 wait()方法都将导致线程阻塞,阻塞的同时也将释放该对象的锁,相应地,调用任意对象的 notify()方法则将随机解除该对象阻塞的线程,但它需要重新获取该对象的锁,直到获取成功才能往下执行;

    其次,wait、notify 方法必须在 synchronized 块或方法中被调用,并且要保证同步块或方法的锁对象与调用 wait、notify 方法的对象是同一个,如此一来在调用 wait 之前当前线程就已经成功获取某对象的锁,执行 wait 阻塞后当前线程就将之前获取的对象锁释放。

    48、解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。

    通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。

    String str = new String("hello");

    上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量是放在方法区的。

    补充1:

    较新版本的Java(从Java 6的某个更新开始)中,由于JIT编译器的发展和”逃逸分析”技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象一定分配在堆上这件事情已经变得不那么绝对了。

    补充2:

    运行时常量池相当于Class文件常量池具有动态性,Java语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String类的intern()方法就是这样的。

    看看下面代码的执行结果是什么并且比较一下Java 7以前和以后的运行结果是否一致。

    String s1 = new StringBuilder("go") .append("od").toString(); System.out.println(s1.intern() == s1); String s2 = new StringBuilder("ja") .append("va").toString(); System.out.println(s2.intern() == s2);

    49、多线程同步有哪几种方法?

    Synchronized关键字,Lock锁实现,分布式锁等。

    50、什么是自旋

    很多 synchronized 里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然 synchronized 里面的代码执行得非常快,不妨让等待锁的线程不要被阻塞,而是在 synchronized 的边界做忙循环,这就是自旋。如果做了多次循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。

    忙循环:就是程序员用循环让一个线程等待,不像传统方法wait(), sleep() 或 yield() 它们都放弃了CPU控制,而忙循环不会放弃CPU,它就是在运行一个空循环。这么做的目的是为了保留CPU缓存,在多核系统中,一个等待线程醒来的时候可能会在另一个内核运行,这样会重建缓存。为了避免重建缓存和减少等待重建的时间就可以使用它了。

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    51、并行和并发有什么区别?

    1、 并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。

    2、 并行:单位时间内,多个处理器或多核处理器同时处理多个任务,是真正意义上的“同时进行”。

    3、 串行:有n个任务,由一个线程按顺序执行。由于任务、方法都在一个线程执行所以不存在线程不安全情况,也就不存在临界区的问题。

    做一个形象的比喻:

    1、 并发 = 俩个人用一台电脑。

    2、 并行 = 俩个人分配了俩台电脑。

    3、 串行 = 俩个人排队使用一台电脑。

    52、Hibernate中SessionFactory是线程安全的吗?Session是线程安全的吗(两个线程能够共享同一个Session吗)?

    SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory一般只会在启动的时候构建。对于应用程序,最好将SessionFactory通过单例模式进行封装以便于访问。Session是一个轻量级非线程安全的对象(线程间不能共享session),它表示与数据库进行交互的一个工作单元。Session是由SessionFactory创建的,在任务完成之后它会被关闭。Session是持久层服务对外提供的主要接口。Session会延迟获取数据库连接(也就是在需要的时候才会获取)。为了避免创建太多的session,可以使用ThreadLocal将session和当前线程绑定在一起,这样可以让同一个线程获得的总是同一个session。Hibernate 3中SessionFactory的getCurrentSession()方法就可以做到。

    53、Java会存在内存泄漏吗?请简单描述。

    内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。理论上来说,Java是有GC垃圾回收机制的,也就是说,不再被使用的对象,会被GC自动回收掉,自动从内存中清除

    但是,即使这样,Java也还是存在着内存泄漏的情况,java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。

    54、生产环境服务器变慢,如何诊断处理?

    1、 使用 top 指令,服务器中 CPU 和 内存的使用情况,-H 可以按 CPU 使用率降序,-M 内存使用率降序。排除其他进程占用过高的硬件资源,对 Java 服务造成影响。

    2、 如果发现 CPU 使用过高,可以使用 top 指令查出 JVM 中占用 CPU 过高的线程,通过 jstack 找到对应的线程代码调用,排查出问题代码。

    3、 如果发现内存使用率比较高,可以 dump 出 JVM 堆内存,然后借助 MAT 进行分析,查出大对象或者占用最多的对象来自哪里,为什么会长时间占用这么多;如果 dump 出的堆内存文件正常,此时可以考虑堆外内存被大量使用导致出现问题,需要借助操作系统指令 pmap 查出进程的内存分配情况、gdb dump 出具体内存信息、perf 查看本地函数调用等。

    4、 如果 CPU 和 内存使用率都很正常,那就需要进一步开启 GC 日志,分析用户线程暂停的时间、各部分内存区域 GC 次数和时间等指标,可以借助 jstat 或可视化工具 GCeasy 等,如果问题出在 GC 上面的话,考虑是否是内存不够、根据垃圾对象的特点进行参数调优、使用更适合的垃圾收集器;分析 jstack 出来的各个线程状态。如果问题实在比较隐蔽,考虑是否可以开启 jmx,使用 visualmv 等可视化工具远程监控与分析。

    55、你是如何理解fiber的?

    React Fiber 是一种基于浏览器的单线程调度算法.

    React 16之前 ,reconcilation 算法实际上是递归,想要中断递归是很困难的,React 16 开始使用了循环来代替之前的递归.

    Fiber一种将 recocilation (递归 diff),拆分成无数个小任务的算法;它随时能够停止,恢复。停止恢复的时机取决于当前的一帧(16ms)内,还有没有足够的时间允许计算。

    Fiber 详解

    56、HashMap的扩容操作是怎么实现的?

    1、 在jdk1.8中,resize方法是在hashmap中的键值对大于阀值时或者初始化时,就调用resize方法进行扩容;

    2、 每次扩展的时候,都是扩展2倍;

    3、 扩展后Node对象的位置要么在原位置,要么移动到原偏移量两倍的位置。

    在putVal()中,我们看到在这个函数里面使用到了2次resize()方法,resize()方法表示的在进行第一次初始化时会对其进行扩容,或者当该数组的实际大小大于其临界值值(第一次为12),这个时候在扩容的同时也会伴随的桶上面的元素进行重新分发,这也是JDK1.8版本的一个优化的地方,在1.7中,扩容之后需要重新去计算其Hash值,根据Hash值对其进行分发,但在1.8版本中,则是根据在同一个桶的位置中进行判断(e.hash & oldCap)是否为0,重新进行hash分配后,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

    final Node < K, V > [] resize() {
        Node < K, V > [] oldTab = table; //oldTab指向hash桶数组
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap > 0) { //如果oldCap不为空的话,就是hash桶数组不为空
            if (oldCap >= MAXIMUM_CAPACITY) { //如果大于最大容量了,就赋值为整数最大的阀值
                threshold = Integer.MAX_VALUE;
                return oldTab; //返回
            } //如果当前hash桶数组的长度在扩容后仍然小于最大容量 并且oldCap大于默认值16
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // double threshold 双倍扩容阀值threshold
        }
        // 旧的容量为0,但threshold大于零,代表有参构造有cap传入,threshold已经被初始化成最小2的n次幂
        // 直接将该值赋给新的容量
        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;
        // 无参构造创建的map,给出默认容量和threshold 16, 16*0.75
        else { // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        // 新的threshold = 新的cap * 0.75
        if (newThr == 0) {
            float ft = (float) newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ? (int) ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        // 计算出新的数组长度后赋给当前成员变量table
        @
        SuppressWarnings({
            "rawtypes", "unchecked"
        })
        Node < K, V > [] newTab = (Node < K, V > []) new Node[newCap]; //新建hash桶数组
        table = newTab; //将新数组的值复制给旧的hash桶数组
        // 如果原先的数组没有初始化,那么resize的初始化工作到此结束,否则进入扩容元素重排逻辑,使其均匀的分散
        if (oldTab != null) {
            // 遍历新数组的所有桶下标
            for (int j = 0; j < oldCap; ++j) {
                Node < K, V > e;
                if ((e = oldTab[j]) != null) {
                    // 旧数组的桶下标赋给临时变量e,并且解除旧数组中的引用,否则就数组无法被GC回收
                    oldTab[j] = null;
                    // 如果e.next==null,代表桶中就一个元素,不存在链表或者红黑树
                    if (e.next == null)
                    // 用同样的hash映射算法把该元素加入新的数组
                        newTab[e.hash & (newCap - 1)] = e;
                    // 如果e是TreeNode并且e.next!=null,那么处理树中元素的重排
                    else if (e instanceof TreeNode)
                    ((TreeNode < K, V > ) e).split(this, newTab, j, oldCap);
                    // e是链表的头并且e.next!=null,那么处理链表中元素重排
                    else { // preserve order
                        // loHead,loTail 代表扩容后不用变换下标,见注1
                        Node < K, V > loHead = null, loTail = null;
                        // hiHead,hiTail 代表扩容后变换下标,见注1
                        Node < K, V > hiHead = null, hiTail = null;
                        Node < K, V > next;
                        // 遍历链表
                        do {
                            next = e.next;
                            if ((e.hash & oldCap) == 0) {
                                if (loTail == null)
                                // 初始化head指向链表当前元素e,e不一定是链表的第一个元素,初始化后loHead
                                // 代表下标保持不变的链表的头元素
                                    loHead = e;
                                else
                                // loTail.next指向当前e
                                    loTail.next = e;
                                // loTail指向当前的元素e
                                // 初始化后,loTail和loHead指向相同的内存,所以当loTail.next指向下一个元素时,
                                // 底层数组中的元素的next引用也相应发生变化,造成lowHead.next.next.....
                                // 跟随loTail同步,使得lowHead可以链接到所有属于该链表的元素。
                                loTail = e;
                            } else {
                                if (hiTail == null)
                                // 初始化head指向链表当前元素e, 初始化后hiHead代表下标更改的链表头元素
                                    hiHead = e;
                                else hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        // 遍历结束, 将tail指向null,并把链表头放入新数组的相应下标,形成新的映射。
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }

    57、解释如何使用WAR文件部署web应用程序?

    在Tomcat的web应用程序目录下,jsp、servlet和它们的支持文件被放置在适当的子目录中。你可以将web应用程序目录下的所有文件压缩到一个压缩文件中,以.war文件扩展名结束。你可以通过在webapps目录中放置WAR文件来执行web应用程序。当一个web服务器开始执行时,它会将WAR文件的内容提取到适当的webapps子目录中。

    58、常用的并发工具类有哪些?

    1、 CountDownLatch

    2、 CyclicBarrier

    3、 Semaphore

    4、 Exchanger

    59、你能保证 GC 执行吗?

    不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC 的执行。

    60、哪些集合类是线程安全的?

    1、 Vector:就比Arraylist多了个 synchronized (线程安全),因为效率较低,现在已经不太建议使用。

    2、 hashTable:就比hashMap多了个synchronized (线程安全),不建议使用。

    3、 ConcurrentHashMap:是Java5中支持高并发、高吞吐量的线程安全HashMap实现。它由Segment数组结构和HashEntry数组结构组成。Segment数组在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键-值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构;一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素;每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。(推荐使用)


    61、JDK 和 JRE 有什么区别?

    JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。

    JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。 具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。

    62、能否使用任何类作为 Map 的 key?

    可以使用任何类作为 Map 的 key,然而在使用之前,需要考虑以下几点:

    1、 如果类重写了 equals() 方法,也应该重写 hashCode() 方法。

    2、 类的所有实例需要遵循与 equals() 和 hashCode() 相关的规则。

    3、 如果一个类没有使用 equals(),不应该在 hashCode() 中使用它。

    4、 用户自定义 Key 类最佳实践是使之为不可变的,这样 hashCode() 值可以被缓存起来,拥有更好的性能。不可变的类也可以确保 hashCode() 和 equals() 在未来不会改变,这样就会解决与可变相关的问题了。

    63、简述synchronized 和java.util.concurrent.locks.Lock的异同?

    Lock是Java 5以后引入的新的API,和关键字synchronized相比主要相同点:Lock 能完成synchronized所实现的所有功能;主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)。

    64、什么是线程组,为什么在Java中不推荐使用?

    ThreadGroup类,可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式。

    为什么不推荐使用?因为使用有很多的安全隐患吧,没有具体追究,如果需要使用,推荐使用线程池。

    65、你所知道的web服务器有哪些?

    1、 Tomcat

    2、 Jboss

    3、 Weblogic

    4、 Glassfish

    66、Java中如何实现序列化,有什么意义?

    序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。

    要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆(可以参考第29题)。

    67、单例模式使用注意事项:

    1、 使用时不能用反射模式创建单例,否则会实例化一个新的对象

    2、 使用懒单例模式时注意线程安全问题

    3、 饿单例模式和懒单例模式构造方法都是私有的,因而是不能被继承的,有些单例模式可以被继承(如登记式模式)

    68、请解释Tomcat的默认端口是什么?

    Tomcat的默认端口是8080。在本地机器上初始化Tomcat之后,您可以验证Tomcat是否正在运行URL:http://localhost:8080

    69、创建线程的有哪些方式?

    1、 继承Thread类创建线程类

    2、 通过Runnable接口创建线程类

    3、 通过Callable和Future创建线程

    4、 通过线程池创建

    70、什么是OOP?

    面向对象编程

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    71、为什么HashMap中String、Integer这样的包装类适合作为K?

    String、Integer等包装类的特性能够保证Hash值的不可更改性和计算准确性,能够有效的减少Hash碰撞的几率

    1、 都是final类型,即不可变性,保证key的不可更改性,不会存在获取hash值不同的情况

    2、 内部已重写了equals()hashCode()等方法,遵守了HashMap内部的规范(不清楚可以去上面看看putValue的过程),不容易出现Hash值计算错误的情况;

    72、常见的计算机网络协议有那些?

    1、 TCP/IP协议

    2、 IPX/SPX协议

    3、 NetBEUI协议

    73、一个线程运行时发生异常会怎样?

    如果异常没有被捕获该线程将会停止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UncaughtExceptionHandler并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。

    74、遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?

    遍历方式有以下几种:

    1、 for 循环遍历,基于计数器。在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。

    2、 迭代器遍历,Iterator。Iterator 是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的接口。Java 在 Collections 中支持了 Iterator 模式。

    3、 foreach 循环遍历。foreach 内部也是采用了 Iterator 的方式实现,使用时不需要显式声明 Iterator 或计数器。优点是代码简洁,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。

    最佳实践:

    Java Collections 框架中提供了一个 RandomAccess 接口,用来标记 List 实现是否支持 Random Access。

    1、 如果一个数据集合实现了该接口,就意味着它支持 Random Access,按位置读取元素的平均时间复杂度为 O(1),如ArrayList。

    2、 如果没有实现该接口,表示不支持 Random Access,如LinkedList。

    3、 推荐的做法就是,支持 Random Access 的列表可用 for 循环遍历,否则建议用 Iterator 或 foreach 遍历。

    75、StringBuffer,Stringbuilder有什么区别?

    StringBuffer与StringBuilder都继承了AbstractStringBulder类,而AbtractStringBuilder又实现了CharSequence接口,两个类都是用来进行字符串操作的。

    在做字符串拼接修改删除替换时,效率比string更高。

    StringBuffer是线程安全的,Stringbuilder是非线程安全的。所以Stringbuilder比stringbuffer效率更高,StringBuffer的方法大多都加了synchronized关键字

    76、什么是线程池?

    Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理地使用线程池能够带来许多好处。

    1、 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

    2、 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

    3、 提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用

    77、JDBC操作的步骤

    1、 加载数据库驱动类

    2、 打开数据库连接

    3、 执行sql语句

    4、 处理返回结果

    5、 关闭资源

    78、说一下 JVM 调优的工具?

    常用调优工具分为两类,jdk自带监控工具:jconsole和jvisualvm,第三方有:MAT(Memory AnalyzerTool)、GChisto。

    jconsole,Java Monitoring and Management Console是从java5开始,在JDK中自带的java监控和管理控制台,用于对JVM中内存, 线程和类等的监控。jvisualvm,jdk自带全能工具,可以分析内存快照、线程快照;监控内存变化、GC变化等。MAT,Memory Analyzer Tool,一个基于Eclipse的内存分析工具,是一个快速、功能丰富的Javaheap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。GChisto,一款专业分析gc日志的工具。

    79、JVM 提供的常用工具

    jps:

    用来显示本地的 Java 进程,可以查看本地运行着几个 Java 程序,并显示他们的进程号。 命令格式:jps

    jinfo:

    运行环境参数:Java System 属性和 JVM 命令行参数,Java class path 等信息。 命令格式:jinfo 进程 pid

    jstat:

    监视虚拟机各种运行状态信息的命令行工具。 命令格式:jstat -gc 123 250 20

    jstack:

    可以观察到 JVM 中当前所有线程的运行情况和线程当前状态。 命令格式:jstack 进程 pid

    jmap:

    观察运行中的 JVM 物理内存的占用情况(如:产生哪些对象,及其数量)。 命令格式:jmap [option] pid

    80、SynchronizedMap和ConcurrentHashMap有什么区别?

    SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能有一个线程来访为map。

    1、 ConcurrentHashMap使用分段锁来保证在多线程下的性能。ConcurrentHashMap中则是一次锁住一个桶。ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

    2、 另外ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。

    81、Java有没有goto?

    goto 是Java中的保留字,在目前版本的Java中没有使用。(根据James Gosling(Java之父)编写的《The Java Programming Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)

    82、JVM怎么判断一个对象是不是要回收?

    引用计数法(缺点是对于相互引用的对象,无法进行清除) 可达性分析

    83、String s = new String(“xyz”);创建了几个字符串对象?

    两个对象,一个是静态区的”xyz”,一个是用new创建在堆上的对象。

    84、什么是过滤器?怎么创建一个过滤器

    过滤器:在请求发送之后,处理之前对请求的一次拦截,可以更改请求状态或者参数值等。

    创建过滤器:实现filter接口,重写doFilter方法,最后在web.xml中配置过滤器

    85、介绍一下 JVM 中垃圾收集器有哪些? 他们特点分别是什么?

    新生代垃圾收集器

    Serial 收集器

    特点: Serial 收集器只能使用一条线程进行垃圾收集工作,并且在进行垃圾收集的时候,所有的工作线程都需要停止工作,等待垃圾收集线程完成以后,其他线程才可以继续工作。

    使用算法:复制算法

    ParNew 收集器

    特点: ParNew 垃圾收集器是Serial收集器的多线程版本。为了利用 CPU 多核多线程的优势,ParNew 收集器可以运行多个收集线程来进行垃圾收集工作。这样可以提高垃圾收集过程的效率。

    使用算法:复制算法

    Parallel Scavenge 收集器

    特点: Parallel Scavenge 收集器是一款多线程的垃圾收集器,但是它又和 ParNew 有很大的不同点。

    Parallel Scavenge 收集器和其他收集器的关注点不同。其他收集器,比如 ParNew 和 CMS 这些收集器,它们主要关注的是如何缩短垃圾收集的时间。而 Parallel Scavenge 收集器关注的是如何控制系统运行的吞吐量。这里说的吞吐量,指的是 CPU 用于运行应用程序的时间和 CPU 总时间的占比,吞吐量 = 代码运行时间 / (代码运行时间 + 垃圾收集时间)。如果虚拟机运行的总的 CPU 时间是 100 分钟,而用于执行垃圾收集的时间为 1 分钟,那么吞吐量就是 99%。

    使用算法:复制算法

    老年代垃圾收集器

    Serial Old 收集器

    特点: Serial Old 收集器是 Serial 收集器的老年代版本。这款收集器主要用于客户端应用程序中作为老年代的垃圾收集器,也可以作为服务端应用程序的垃圾收集器。

    使用算法:标记-整理

    Parallel Old 收集器

    特点: Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本这个收集器是在 JDK1.6 版本中出现的,所以在 JDK1.6 之前,新生代的 Parallel Scavenge 只能和 Serial Old 这款单线程的老年代收集器配合使用。Parallel Old 垃圾收集器和 Parallel Scavenge 收集器一样,也是一款关注吞吐量的垃圾收集器,和 Parallel Scavenge 收集器一起配合,可以实现对 Java 堆内存的吞吐量优先的垃圾收集策略。

    使用算法:标记-整理

    CMS 收集器

    特点: CMS 收集器是目前老年代收集器中比较优秀的垃圾收集器。CMS 是 Concurrent Mark Sweep,从名字可以看出,这是一款使用"标记-清除"算法的并发收集器。

    CMS 垃圾收集器是一款以获取最短停顿时间为目标的收集器。如下图所示:

    从图中可以看出,CMS 收集器的工作过程可以分为 4 个阶段:

    1、 初始标记(CMS initial mark)阶段

    2、 并发标记(CMS concurrent mark)阶段

    3、 重新标记(CMS remark)阶段

    4、 并发清除((CMS concurrent sweep)阶段

    使用算法:复制+标记清除

    其他

    G1 垃圾收集器

    特点: 主要步骤:初始标记,并发标记,重新标记,复制清除。

    使用算法:复制 + 标记整理

    86、线程池的执行原理?

    提交一个任务到线程池中,线程池的处理流程如下:

    1、 判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。

    2、 线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

    3、 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

    87、假设数组内有5个元素,如果对数组进行反序,该如何做?

    创建一个新数组,从后到前循环遍历每个元素,将取出的元素依次顺序放入新数组中

    88、java 中 IO 流分为几种?

    按功能来分:输入流(input)、输出流(output)。

    按类型来分:字节流和字符流。

    字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

    89、你都有哪些手段用来排查内存溢出?

    (这个话题很大,可以从实践环节中随便摘一个进行总结,下面举例一个最普通的)

    你可以来一个中规中矩的回

    内存溢出包含很多种情况,我在平常工作中遇到最多的就是堆溢出。有一次线上遇到故障,重新启动后,使用jstat命令,发现Old区在一直增长。我使用jmap命令,导出了一份线上堆栈,然后使用MAT进行分析。通过对GC Roots的分析,我发现了一个非常大的HashMap对象,这个原本是有位同学做缓存用的,但是一个无界缓存,造成了堆内存占用一直上升。后来,将这个缓存改成 guava的Cache,并设置了弱引用,故障就消失了。

    这个回答不是十分出彩,但着实是常见问题,让人挑不出毛病。

    90、GC 是什么?为什么要有 GC?

    GC 是垃 圾收 集的 意思 ,内存 处理 是编 程人 员容 易出 现问 题的 地方 ,忘记 或者 错误的内 存回 收会 导致 程序 或系 统的 不稳 定甚 至崩 溃, Java 提供 的 GC 功能 可以 自动监测 对象 是否 超过 作用 域从 而达 到自 动回 收内 存的 目的 ,Java 语言 没有 提供 释放已分配内存的 显示 操作 方法 。Java 程序 员不 用担 心内 存管 理, 因为 垃圾 收集 器会自动 进行 管理 。要 请求 垃圾 收集 ,可 以调 用下 面的 方法 之一 :System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以 屏蔽 掉线 示的 垃圾 回收 调用 。

    垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在 Java 诞生初期,垃圾回收是 Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东。移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性。

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    91、你说你做过JVM参数调优和参数配置,请问如何查看JVM系统默认值

    使用-XX:+PrintFlagsFinal参数可以看到参数的默认值。这个默认值还和垃圾回收器有关,比如UseAdaptiveSizePolicy。

    92、Java 中怎样将 bytes 转换为 long 类型?

    这个问题你来回答 :-)

    93、如何避免线程死锁

    1、 避免一个线程同时获得多个锁

    2、 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源

    3、 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制

    94、生产环境 CPU 占用过高,你如何解决?

    1、 top + H 指令找出占用 CPU 最高的进程的 pid

    2、 top -H -p

    在该进程中找到,哪些线程占用的 CPU 最高的线程,记录下 tid

    3、 jstack -l

    threads.txt,导出进程的线程栈信息到文本,导出出现异常的话,加上 -F 参数

    4、 将 tid 转换为十六进制,在 threads.txt 中搜索,查到对应的线程代码执行栈,在代码中查找占 CPU 比较高的原因。其中 tid 转十六进制,可以借助 Linux 的 printf "%x" tid 指令

    我用上述方法查到过,jvm 多条线程疯狂 full gc 导致的CPU 100% 的问题和 JDK1.6 HashMap 并发 put 导致线程 CPU 100% 的问题

    95、同步方法和同步块,哪个是更好的选择?

    同步块是更好的选择,因为它不会锁住整个对象(当然你也可以让它锁住整个对象)。同步方法会锁住整个对象,哪怕这个类中有多个不相关联的同步块,这通常会导致他们停止执行并需要等待获得这个对象上的锁。

    同步块更要符合开放调用的原则,只在需要锁住的代码块锁住相应的对象,这样从侧面来说也可以避免死锁。

    96、自动装箱与拆箱

    装箱:将基本类型用它们对应的引用类型包装起来;

    拆箱:将包装类型转换为基本数据类型;

    Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

    97、详细介绍一下JVM内存模型

    根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。

    具体可能会聊聊jdk1.7以前的PermGen(永久代),替换成Metaspace(元空间)

    1、 原本永久代存储的数据:符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap

    2、 Metaspace(元空间)存储的是类的元数据信息(metadata)

    3、 元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。

    4、 替换的好处:一、字符串存在永久代中,容易出现性能问题和内存溢出。二、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

    98、监听器有哪些作用和用法?

    ava Web开发中的监听器(listener)就是application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:

    1、 ServletContextListener:对Servlet上下文的创建和销毁进行监听。

    2、 ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。

    3、 HttpSessionListener:对Session的创建和销毁进行监听。

    99、说一下堆内存中对象的分配的基本策略

    eden区、s0区、s1区都属于新生代,tentired 区属于老年代。大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden区->Survivor 区后对象的初始年龄变为1),当它的年龄增加到一定程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。另外,大对象和长期存活的对象会直接进入老年代。

    100、HashSet与HashMap的区别

    101、线程和进程区别

    什么是线程和进程?

    进程

    一个在内存中运行的应用程序。 每个正在系统上运行的程序都是一个进程

    线程

    进程中的一个执行任务(控制单元), 它负责在程序里独立执行。

    一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据

    进程与线程的区别

    102、 根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

    2、 资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

    3、 包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

    4、 内存分配:同一进程的线程共享本进程的地址空间和资源,而进程与进程之间的地址空间和资源是相互独立的

    5、 影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃有可能导致整个进程都死掉。所以多进程要比多线程健壮。

    6、 执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

    102、列举一些你知道的打破双亲委派机制的例子。为什么要打破?

    1、 JNDI 通过引入线程上下文类加载器,可以在 Thread.setContextClassLoader 方法设置,默认是应用程序类加载器,来加载 SPI 的代码。有了线程上下文类加载器,就可以完成父类加载器请求子类加载器完成类加载的行为。打破的原因,是为了 JNDI 服务的类加载器是启动器类加载,为了完成高级类加载器请求子类加载器(即上文中的线程上下文加载器)加载类。

    2、 Tomcat,应用的类加载器优先自行加载应用目录下的 class,并不是先委派给父加载器,加载不了才委派给父加载器。打破的目的是为了完成应用间的类隔离。

    3、 OSGi,实现模块化热部署,为每个模块都自定义了类加载器,需要更换模块时,模块与类加载器一起更换。其类加载的过程中,有平级的类加载器加载行为。打破的原因是为了实现模块热替换。

    4、 JDK 9,Extension ClassLoader 被 Platform ClassLoader 取代,当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中,如果可以找到这样的归属关系,就要优先委派给负责那个模块的加载器完成加载。打破的原因,是为了添加模块化的特性。

    103、CopyOnWriteArrayList可以用于什么应用场景?

    CopyOnWriteArrayList(免锁容器)的好处之一是当多个迭代器同时遍历和修改这个列表时,不会抛出ConcurrentModificationException。在CopyOnWriteArrayList中,写入将导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行。

    1、 由于写操作的时候,需要拷贝数组,会消耗内存,如果原数组的内容比较多的情况下,可能导致young gc或者full gc;

    2、 不能用于实时读的场景,像拷贝数组、新增元素都需要时间,所以调用一个set操作后,读取到数据可能还是旧的,虽然CopyOnWriteArrayList 能做到最终一致性,但是还是没法满足实时性要求;

    CopyOnWriteArrayList透露的思想

    1、 读写分离,读和写分开

    2、 最终一致性

    3、 使用另外开辟空间的思路,来解决并发冲突

    104、我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?

    是的,我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化是,int 类型的高 24 位将会被丢弃,byte 类型的范围是从 -128 到 128。

    105、成员变量与局部变量的区别有那些?

    1、 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;成员变量和局部变量都能被final所修饰;

    2、 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存

    3、 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。

    4、 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。

    106、哪些是 GC Roots?

    1、 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。

    2、 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。

    3、 在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。

    4、 在本地方法栈中JNI(即通常所说的Native方法)引用的对象。

    5、 Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如 NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。

    6、 所有被同步锁(synchronized关键字)持有的对象。

    7、 反映 Java 虚拟机内部情况的 JMXBean、JVMTI中注册的回调、本地代码缓存等。

    107、你能解释一下里氏替换原则吗?

    https://blog.csdn.net/pu_xubo565599455/article/details/51488323

    108、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?

    双亲委托模型的重要用途是为了解决类载入过程中的安全性问题。

    1、 假设有一个开发者自己编写了一个名为java.lang.Object的类,想借此欺骗JVM。现在他要使用自定义ClassLoader来加载自己编写的java.lang.Object类。

    2、 然而幸运的是,双亲委托模型不会让他成功。因为JVM会优先在Bootstrap ClassLoader的路径下找到java.lang.Object类,并载入它

    Java的类加载是否一定遵循双亲委托模型?

    1、 在实际开发中,我们可以通过自定义ClassLoader,并重写父类的loadClass方法,来打破这一机制。

    2、 SPI就是打破了双亲委托机制的(SPI:服务提供发现)。

    109、为什么Thread类的sleep()和yield ()方法是静态的?

    Thread类的sleep()和yield()方法将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。

    110、在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

    在 java 虚拟机中,监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。

    一旦方法或者代码块被 synchronized 修饰,那么这个部分就放入了监视器的监视区域,确保一次只能有一个线程执行该部分的代码,线程在获取锁之前不允许执行该部分的代码

    另外 java 还提供了显式监视器( Lock )和隐式监视器( synchronized )两种锁方案

    111、线程与进程的区别

    进程是系统进行资源分配和调度的一个独立单位,线程是CPU调度和分派的基本单位

    进程和线程的关系:

    1、 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

    2、 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

    3、 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

    4、 线程是指进程内的一个执行单元,也是进程内的可调度实体。

    线程与进程的区别:

    1、 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

    2、 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

    3、 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。

    4、 系统开销:在创建或撤销进程的时候,由于系统都要为之分配和回收资源,导致系统的明显大于创建或撤销线程时的开销。但进程有独立的地址空间,进程崩溃后,在保护模式下不会对其他的进程产生影响,而线程只是一个进程中的不同的执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但是在进程切换时,耗费的资源较大,效率要差些。

    112、什么是策略模式

    定义了一系列的算法 或 逻辑 或 相同意义的操作,并将每一个算法、逻辑、操作封装起来,而且使它们还可以相互替换。(其实策略模式Java中用的非常非常广泛)

    我觉得主要是为了 简化 if...else 所带来的复杂和难以维护。

    113、什么是游标?

    游标是sql查询结果集的一个指针,与select语句相关联。

    游标关键字是cursor,主要包含两个部分:游标结果集和游标位置。

    1、 游标结果集:执行select语句后的查询结果

    2、 游标位置:一个指向游标结果集内某条记录的指针。

    游标主要有两个状态:打开和关闭。

    1、 只有当游标处于打开状态时,才能够操作结果集中的数据

    2、 当游标关闭后,查询结果集就不存在了

    114、单例模式了解吗?给我解释一下双重检验锁方式实现单例模式!”

    双重校验锁实现对象单例(线程安全)

    说明:

    双锁机制的出现是为了解决前面同步问题和性能问题,看下面的代码,简单分析下确实是解决了多线程并行进来不会出现重复new对象,而且也实现了懒加载

    public class Singleton {
           private volatile static Singleton uniqueInstance;
    
           private Singleton() {
           }
    
          public static Singleton getUniqueInstance() {
                //先判断对象是否已经实例过,没有实例化过才进入加锁代码
                if (uniqueInstance == null) {
                    //类对象加锁
                    synchronized (Singleton.class) {
                        if (uniqueInstance == null) {
                            uniqueInstance = new Singleton();
                        }
                    }
                }
              return uniqueInstance;
          }
     }

    另外,需要注意 uniqueInstance 采用 volatile 关键字修饰也是很有必要。

    uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:

    1、 为 uniqueInstance 分配内存空间

    2、 初始化 uniqueInstance

    3、 将 uniqueInstance 指向分配的内存地址

    但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。

    使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。

    115、怎么获取 Java 程序使用的内存?堆使用的百分比?

    可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory()方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。

    116、在java中守护线程和本地线程区别?

    java中的线程分为两种:守护线程(Daemon)和用户线程(User)。

    任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。

    两者的区别

    唯一的区别是判断虚拟机(JVM)何时离开,Daemon是为其他线程提供服务,如果全部的User Thread已经撤离,Daemon 没有可服务的线程,JVM撤离。也可以理解为守护线程是JVM自动创建的线程(但不一定),用户线程是程序创建的线程;比如JVM的垃圾回收线程是一个守护线程,当所有线程已经撤离,不再产生垃圾,守护线程自然就没事可干了,当垃圾回收线程是Java虚拟机上仅剩的线程时,Java虚拟机会自动离开。

    扩展

    Thread Dump打印出来的线程信息,含有daemon字样的线程即为守护进程,可能会有:服务守护进程、编译守护进程、windows下的监听Ctrl+break的守护进程、Finalizer守护进程、引用处理守护进程、GC守护进程。

    117、线程之间是如何通信的?

    当线程间是可以共享资源时,线程间通信是协调它们的重要的手段。Object类中wait()\notify()\notifyAll()方法可以用于线程间通信关于资源的锁的状态。

    118、聚集索引与非聚集索引有什么区别?

    所有的索引都是为了更快地检索数据,索引存放在索引页中,数据存放在数据页中,索引以B(balance)树的形式存储

    聚集索引:聚集索引用于决定数据表中的物理存储顺序,一张表最多有一个聚集索引。聚集索引的字段值尽量不能修改,因为修改后,因为修改后数据表的物理顺序需要重写排序。通常主键就是聚集索引

    非聚集索引:非聚集索引的关键自是index,不会决定表的物理存储顺序,在一张表内最多可以有249个非聚集索引。

    119、说一下 ArrayList 的优缺点

    ArrayList的优点如下:

    1、 ArrayList 底层以数组实现,是一种随机访问模式。ArrayList 实现了 RandomAccess 接口,因此查找的时候非常快。

    2、 ArrayList 在顺序添加一个元素的时候非常方便。

    ArrayList 的缺点如下:

    1、 删除元素的时候,需要做一次元素复制操作。如果要复制的元素很多,那么就会比较耗费性能。

    2、 插入元素的时候,也需要做一次元素复制操作,缺点同上。

    3、 ArrayList 比较适合顺序添加、随机访问的场景。

    120、请解释StackOverflowError和OutOfMemeryError的区别?

    通过之前的分析可以发现,实际上每一块内存中都会存在有一部分的可变伸缩区,其基本流程为:如果空间内存不足,在可变范围之内扩大内存空间,当一段时间之后发现内存充足,会缩小内存空间。

    永久代(JDK 1.8后消失了)

    虽然java的版本是JDK1.8,但是java EE 的版本还是jdk1.7,永久代存在于堆内存之中

    元空间

    元空间在Jdk1.8之后才有的,器功能实际上和永久代没区别,唯一的区别在于永久代使用的是JVM的堆内存空间,元空间使用的是物理内存,所以元空间的大小受本地内存影响,一般默认在2M 左右。

    范例:设置一些参数,让元空间出错

    Java -XX:MetaspaceSize=1m

    121、什么是方法内联?

    为了减少方法调用的开销,可以把一些短小的方法,比如getter/setter,纳入到目标方法的调用范围之内,就少了一次方法调用,速度就能得到提升,这就是方法内联的概念。

    122、你对线程优先级的理解是什么?

    1、 每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OS dependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个 int 变量(从 1-10),1 代表最低优先级,10 代表最高优先级。

    2、 Java 的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别需要,一般无需设置线程优先级。

    3、 当然,如果你真的想设置优先级可以通过setPriority()方法设置,但是设置了不一定会该变,这个是不准确的

    123、Java是否需要开发人员回收内存垃圾吗?

    大多情况下是不需要的。Java提供了一个系统级的线程来跟踪内存分配,不再使用的内存区将会自动回收

    124、说说Java 垃圾回收机制

    在 Java 中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在 JVM 中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

    125、volatile 变量和 atomic 变量有什么不同?

    Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用volatile修饰count变量那么 count++ 操作就不是原子性的。

    而AtomicInteger类提供的atomic方法可以让这种操作具有原子性如getAndIncrement()方法会原子性的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。

    126、JVM 内存区域

    JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA 堆、方法区】、直接内存。

    线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 Hotspot VM 内, 每个线程都与操作系统的本地线程直接映射, 因此这部分内存区域的存/否跟随本地线程的生/死对应)。

    线程共享区域随虚拟机的启动/关闭而创建/销毁。

    直接内存并不是 JVM 运行时数据区的一部分, 但也会被频繁的使用: 在 JDK 1.4 引入的 NIO 提供了基于Channel与 Buffer的IO方式, 它可以使用Native函数库直接分配堆外内存, 然后使用DirectByteBuffer 对象作为这块内存的引用进行操作(详见: Java I/O 扩展), 这样就避免了在 Java堆和 Native 堆中来回复制数据, 因此在一些场景中可以显著提高性能。

    127、JVM 有哪些运行时内存区域?

    Java 8

    1、 The pc Register,程序计数器

    2、 Java Virtual Machine Stacks,Java 虚拟机栈

    3、 Heap,堆

    4、 Method Area,方法区

    5、 Run-Time Constant Pool,运行时常量池

    6、 Native Method Stacks,本地方法栈

    128、Spring中Bean的作用域有哪些?

    1、 Singleton:Bean以单例的方式存在

    2、 Prototype:表示每次从容器中调用Bean时,都会返回一个新的实例,prototype通常翻译为原型

    3、 Request:每次HTTP请求都会创建一个新的Bean

    4、 Session:同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean

    5、 globalSession:同一个全局Session共享一个Bean

    129、String str=”aaa”,与String str=new String(“aaa”)一样吗?

    1、 不一样的。因为内存分配的方式不一样。

    2、 第一种,创建的”aaa”是常量,jvm都将其分配在常量池中。

    3、 第二种创建的是一个对象,jvm将其值分配在堆内存中。

    130、什么是建造者模式

    1、 建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的方式进行创建。

    2、 工厂类模式是提供的是创建单个类的产品

    3、 而建造者模式则是将各种产品集中起来进行管理,用来具有不同的属性的产品

    建造者模式通常包括下面几个角色:

    1、 uilder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

    2、 ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

    3、 Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

    4、 Product:要创建的复杂对象。

    131、说说G1垃圾收集器的工作原理

    优点:指定最大停顿时间、分Region的内存布局、按收益动态确定回收集

    1、 G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。虽然G1也仍是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的差异:G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。

    2、 虽然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它们都是一系列区域(不需要连续)的动态集合。G1收集器之所以能建立可预测的停顿时间模型,是因为它将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个Java堆中进行全区域的垃圾收集。更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。这种使用Region划分内存空间,以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内获取尽可能高的收集效率。

    3、 G1收集器的运作过程大致可划分为以下四个步骤:·初始标记 (Initial Marking):仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。·并发标记 (Concurrent Marking):从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。·最终标记 (Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。·筛选回收 (Live Data Counting and Evacuation):负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。从上述阶段的描述可以看出,G1收集器除了并发标记外,其余阶段也是要完全暂停用户线程的 。

    132、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 应用的性能。

    133、当父类引用指向子类对象的时候,子类重写了父类方法和属性,那么当访问属性的时候,访问是谁的属性?调用方法时,调用的是谁的方法?

    子类重写了父类方法和属性,访问的是父类的属性,调用的是子类的方法

    134、堆溢出的原因?

    堆用于存储对象实例,只要不断创建对象并保证 GC Roots 到对象有可达路径避免垃圾回收,随着对象数量的增加,总容量触及最大堆容量后就会 OOM,例如在 while 死循环中一直 new 创建实例。

    堆 OOM 是实际应用中最常见的 OOM,处理方法是通过内存映像分析工具对 Dump 出的堆转储快照分析,确认内存中导致 OOM 的对象是否必要,分清到底是内存泄漏还是内存溢出。

    如果是内存泄漏,通过工具查看泄漏对象到 GC Roots 的引用链,找到泄露对象是通过怎样的引用路径、与哪些 GC Roots 关联才导致无法回收,一般可以准确定位到产生内存泄漏代码的具***置。

    如果不是内存泄漏,即内存中对象都必须存活,应当检查 JVM 堆参数,与机器内存相比是否还有向上调整的空间。再从代码检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行期的内存消耗。

    135、说一下 runnable 和 callable 有什么区别

    相同点:

    1、 都是接口

    2、 都可以编写多线程程序

    3、 都采用Thread.start()启动线程

    主要区别:

    Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

    Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常,可以获取异常信息 注:Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。

    136、JVM 类加载机制

    JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化。

    加载

    加载是类加载过程中的一个阶段, 这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对象, 作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个 Class 文件获取,这里既可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。

    验证

    这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

    准备

    准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:

    实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080, 将 v 赋值为 8080 的 put static 指令是程序被编译后, 存放于类构造器方法之中。

    但是注意如果声明为:

    public static final int v = 8080;

    在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

    解析

    解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的

    public static int v = 8080;

    实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080, 将 v 赋值为 8080 的 put static 指令是程序被编译后, 存放于类构造器方法之中。但是注意如果声明为:

    在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

    解析

    解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的

    public static final int v = 8080;

    在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

    解析

    解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的:

    1、 CONSTANT_Class_info

    2、 CONSTANT_Field_info

    3、 CONSTANT_Method_info

    等类型的常量。

    符号引用

    符号引用与虚拟机实现的布局无关, 引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中。

    直接引用

    直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。

    初始化

    初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。

    类构造器

    初始化阶段是执行类构造器方法的过程。方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子方法执行之前,父类的方法已经执行完毕, 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。

    注意以下几种情况不会执行类初始化:

    1、 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。

    2、 定义对象数组,不会触发该类的初始化。

    3、 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。

    4、 通过类名获取 Class 对象,不会触发类的初始化。

    5、 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。

    6、 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作。

    137、怎么打破双亲委派模型?

    打破双亲委派机制则不仅要继承ClassLoader类,还要重写loadClass和findClass方法。

    138、垃圾收集算法

    GC最基础的算法有三种:标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。

    标记 -清除算法

    “标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

    复制算法

    “复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

    标记-压缩算法

    标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

    分代收集算法

    “分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法

    139、你有哪些手段来排查 OOM 的问题?

    1、 增加两个参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof,当 OOM 发生时自动 dump 堆内存信息到指定目录

    2、 同时 jstat 查看监控 JVM 的内存和 GC 情况,先观察问题大概出在什么区域

    3、 使用 MAT 工具载入到 dump 文件,分析大对象的占用情况,比如 HashMap 做缓存未清理,时间长了就会内存溢出,可以把改为弱引用


    140、假设把实例化的数组的变量当成方法参数,当方法执行的时候改变了数组内的元素,那么在方法外,数组元素有发生改变吗?

    改变了,因为传递是对象的引用,操作的是引用所指向的对象

    这套7000多页的Java面试题 PDF 大全,希望对大家有帮助哈~

    已经整理成7000多页,面试手册PDF版

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个面试手册,是PDF版的

    展开全文
  • 所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~Java面试永远是程序员迈向成功的第一个门槛,想要面试成功,各种面试题的洗礼是必不可少的,下面就来看看小编精心整理的一些Java工程师面试...

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~

    Java面试永远是程序员迈向成功的第一个门槛,想要面试成功,各种面试题的洗礼是必不可少的,下面就来看看小编精心整理的一些Java工程师面试题及答案吧。

    博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的。

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的

    1、64 位 JVM 中,int 的长度是多数?

    Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。

    2、线程的状态

    **1、**新建(new):新创建了一个线程对象。

    **2、**就绪(可运行状态)(runnable):线程对象创建后,当调用线程对象的 start()方法,该线程处于就绪状态,等待被线程调度选中,获取cpu的使用权。

    **3、**运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    **4、**阻塞(block):处于运行状态中的线程由于某种原因,暂时放弃对 CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被 CPU 调用以进入到运行状态。

    阻塞的情况分三种:

    **1、**等待阻塞:

    运行状态中的线程执行 wait()方法,JVM会把该线程放入等待队列(waitting queue)中,使本线程进入到等待阻塞状态;

    **2、**同步阻塞:

    线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用),,则JVM会把该线程放入锁池(lock pool)中,线程会进入同步阻塞状态;

    **3、**其他阻塞:

    通过调用线程的 sleep()或 join()或发出了 I/O 请求时,线程会进入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入就绪状态。

    **4、**死亡(dead)(结束):

    线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

    3、计算机网络有几层?

    **1、**应用层

    **2、**表示层

    **3、**会话层

    **4、**传输层

    **5、**网络层

    **6、**数据链路层

    **7、**物理层

    8、(物理层是最底层,应用层是最高层)

    4、模块化编程与热插拔

    OSGi 旨在为实现 Java 程序的模块化编程提供基础条件,基于 OSGi 的程序很可能可以实现模块级的热插拔功能,当程序升级更新时,可以只停用、重新安装然后启动程序的其中一部分,这对企业级程序开发来说是非常具有诱惑力的特性。

    OSGi 描绘了一个很美好的模块化开发目标,而且定义了实现这个目标的所需要服务与架构,同时也有成熟的框架进行实现支持。但并非所有的应用都适合采用 OSGi 作为基础架构,它在提供强大功能同时,也引入了额外的复杂度,因为它不遵守了类加载的双亲委托模型。

    5、我们能自己写一个容器类,然后使用 for-each 循环码?

    可以,你可以写一个自己的容器类。如果你想使用 Java 中增强的循环来遍历,你只需要实现 Iterable 接口。如果你实现 Collection 接口,默认就具有该属性。

    6、单例防止反射漏洞攻击

    private static boolean flag = false; private Singleton() { if (flag == false) { flag = !flag; } else { throw new RuntimeException(“单例模式被侵犯!”); } } public static void main(String[] args) { }

    7、工作中常用的 JVM 配置参数有哪些?

    Java 8 为例

    日志

    1、-XX:+PrintFlagsFinal,打印JVM所有参数的值

    2、-XX:+PrintGC,打印GC信息

    3、-XX:+PrintGCDetails,打印GC详细信息

    4、-XX:+PrintGCTimeStamps,打印GC的时间戳

    5、-Xloggc:filename,设置GC log文件的位置

    6、-XX:+PrintTenuringDistribution,查看熬过收集后剩余对象的年龄分布信息

    内存设置

    1、-Xms,设置堆的初始化内存大小

    2、-Xmx,设置堆的最大内存

    3、-Xmn,设置新生代内存大小

    4、-Xss,设置线程栈大小

    5、-XX:NewRatio,新生代与老年代比值

    6、-XX:SurvivorRatio,新生代中Eden区与两个Survivor区的比值,默认为8,即Eden:Survivor:Survivor=8:1:1

    7、-XX:MaxTenuringThreshold,从年轻代到老年代,最大晋升年龄。CMS 下默认为 6,G1 下默认为 15

    8、-XX:MetaspaceSize,设置元空间的大小,第一次超过将触发 GC

    9、-XX:MaxMetaspaceSize,元空间最大值

    10、-XX:MaxDirectMemorySize,用于设置直接内存的最大值,限制通过 DirectByteBuffer 申请的内存

    11、-XX:ReservedCodeCacheSize,用于设置 JIT 编译后的代码存放区大小,如果观察到这个值有限制,可以适当调大,一般够用即可

    设置垃圾收集相关

    1、-XX:+UseSerialGC,设置串行收集器

    2、-XX:+UseParallelGC,设置并行收集器

    3、-XX:+UseConcMarkSweepGC,使用CMS收集器

    4、-XX:ParallelGCThreads,设置Parallel GC的线程数

    5、-XX:MaxGCPauseMillis,GC最大暂停时间 ms

    6、-XX:+UseG1GC,使用G1垃圾收集器

    CMS 垃圾回收器相关

    1、-XX:+UseCMSInitiatingOccupancyOnly

    2、-XX:CMSInitiatingOccupancyFraction,与前者配合使用,指定MajorGC的发生时机

    3、-XX:+ExplicitGCInvokesConcurrent,代码调用 System.gc() 开始并行 FullGC,建议加上这个参数

    4、-XX:+CMSScavengeBeforeRemark,表示开启或关闭在 CMS 重新标记阶段之前的清除(YGC)尝试,它可以降低 remark 时间,建议加上

    5、-XX:+ParallelRefProcEnabled,可以用来并行处理 Reference,以加快处理速度,缩短耗时

    G1 垃圾回收器相关

    1、-XX:MaxGCPauseMillis,用于设置目标停顿时间,G1 会尽力达成

    2、-XX:G1HeapRegionSize,用于设置小堆区大小,建议保持默认

    3、-XX:InitiatingHeapOccupancyPercent,表示当整个堆内存使用达到一定比例(默认是 45%),并发标记阶段就会被启动

    4、-XX:ConcGCThreads,表示并发垃圾收集器使用的线程数量,默认值随 JVM 运行的平台不同而变动,不建议修改

    参数查询官网地址:

    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

    建议面试时最好能记住 CMS 和 G1的参数,特点突出使用较多,被问的概率大

    8、面向对象的特征有哪些方面?

    面向对象的特征主要有以下几个方面:

    **1、**抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

    **2、**继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Java与模式》或《设计模式精解》中关于桥梁模式的部分)。

    **3、**封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

    **4、**多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1)、方法重写(子类继承父类并重写父类中已有的或抽象的方法);2)、对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

    9、是否了解连接池,使用连接池有什么好处?

    数据库连接是非常消耗资源的,影响到程序的性能指标。连接池是用来分配、管理、释放数据库连接的,可以使应用程序重复使用同一个数据库连接,而不是每次都创建一个新的数据库连接。通过释放空闲时间较长的数据库连接避免数据库因为创建太多的连接而造成的连接遗漏问题,提高了程序性能。

    10、JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用

    当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM主要动机在于可以指定最大堆大小,通过压缩OOP 可以节省一定的内存。通过-XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。

    11、创建socket通讯的步骤?

    **1、**服务器程序创建一个ServerSocket,然后再用accept方法等待客户来连接

    **2、**客户端程序创建一个Socket并请求与服务器建立连接

    **3、**服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接

    **4、**刚才建立了连接的两个Socket在一个线程上对话

    **5、**服务器开始等待新的连接请求

    12、Java 中 sleep 方法和 wait 方法的区别?

    虽然两者都是用来暂停当前运行的线程,但是 sleep() 实际上只是短暂停顿,因为它不会释放锁,而 wait() 意味着条件等待,这就是为什么该方法要释放锁,因为只有这样,其他等待的线程才能在满足条件时获取到该锁。

    13、程序计数器(线程私有)

    一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有” 的内存。

    正在执行 java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址) 。如果还是 Native 方法,则为空。

    这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域。

    14、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

    线程调度器是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。

    15、迭代器 Iterator 是什么?

    Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。

    因为所有Collection接继承了Iterator迭代器

    16、线程的 sleep()方法和 yield()方法有什么区别?

    **1、**sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

    **2、**线程执行 sleep()方法后转入阻塞(blocked)状态,而执行 yield()方法后转入就绪(ready)状态;

    **3、**sleep()方法声明抛出 InterruptedException,而 yield()方法没有声明任何异常;

    **4、**sleep()方法比 yield()方法(跟操作系统 CPU 调度相关)具有更好的可移植性,通常不建议使用yield()方法来控制并发线程的执行。

    17、Java 中能创建 volatile 数组吗?

    能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。

    18、java中equals方法的用法以及==的用法

    tech.souyunku.com/bluestorm/a…

    19、如何创建一个json对象?

    使用{}实例化一个json对象,json对象多个元素使用逗号隔开,每个元素都是一个键值对

    20、如何判断对象是否是垃圾?

    引用计数:在对象中添加一个引用计数器,如果被引用计数器加 1,引用失效时计数器减 1,如果计数器为 0 则被标记为垃圾。原理简单,效率高,但是在 Java 中很少使用,因为存在对象间循环引用的问题,导致计数器无法清零。

    可达性分析:主流语言的内存管理都使用可达性分析判断对象是否存活。基本思路是通过一系列称为 GC Roots 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程走过的路径称为引用链,如果某个对象到 GC Roots 没有任何引用链相连,则会被标记为垃圾。可作为 GC Roots 的对象包括虚拟机栈和本地方法栈中引用的对象、类静态属性引用的对象、常量引用的对象。

    21、抽象工厂模式和原型模式之间的区别?

    抽象工厂模式:通常由工厂方法模式来实现。但一个工厂中往往含有多个工厂方法生成一系列的产品。这个模式强调的是客户代码一次保证只使用一个系列的产品。当要切换为另一个系列的产品,换一个工厂类即可。

    原型模式:工厂方法的最大缺点就是,对应一个继承体系的产品类,要有一个同样复杂的工厂类的继承体系。我们可以把工厂类中的工厂方法放到产品类自身之中吗?如果这样的话,就可以将两个继承体系为一个。这也就是原型模式的思想,原型模式中的工厂方法为clone,它会返回一个拷贝(可以是浅拷贝,也可以是深拷贝,由设计者决定)。为了保证用户代码中到时可以通过指针调用clone来动态绑定地生成所需的具体的类。这些原型对象必须事先构造好。

    原型模式想对工厂方法模式的另一个好处是,拷贝的效率一般对构造的效率要高。

    22、在 Java 程序中怎么保证多线程的运行安全?

    出现线程安全问题的原因一般都是三个原因:

    **1、**线程切换带来的原子性问题 解决办法:使用多线程之间同步synchronized或使用锁(lock)。

    **2、**缓存导致的可见性问题 解决办法:synchronized、volatile、LOCK,可以解决可见性问题

    **3、**编译优化带来的有序性问题 解决办法:Happens-Before 规则可以解决有序性问题

    23、volatile 修饰符的有过什么实践?

    一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

    24、Java中各种数据默认值

    **1、**Byte,short,int,long默认是都是0

    **2、**Boolean默认值是false

    **3、**Char类型的默认值是’’

    **4、**Float与double类型的默认是0.0

    **5、**对象类型的默认值是null

    25、说说Java 垃圾回收机制

    在 Java 中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在 JVM 中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

    26、有没有可能两个不相等的对象有有相同的 hashcode?

    有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。相等 hashcode 值的规定只是说如果两个对象相等,必须有相同的hashcode 值,但是没有关于不相等对象的任何规定。

    27、synchronized 和 Lock 有什么区别?

    **1、**首先synchronized是Java内置关键字,在JVM层面,Lock是个Java类;

    **2、**synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。

    **3、**synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。

    **4、**通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

    28、什么是Vector

    Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,访问它比访问ArrayList慢很多

    ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。ArrayList的缺点是每个元素之间不能有间隔。

    29、对象的访问定位有哪几种方式?

    建立对象就是为了使用对象,我们的Java程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式有虚拟机实现而定,目前主流的访问方式有使用句柄和直接指针2种:

    句柄:如果使用句柄的话,那么Java堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。

    直接指针:如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference 中存储的直接就是对象的地址。

    这两种对象访问方式各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。使用直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销。

    30、equals 和 == 的区别?#

    通俗点讲:是看看左右是不是一个东西。equals是看看左右是不是长得一样。如何记住嘛。如果单纯是想记住,:等于。equals:相同。两个长得一样的人,只能说长的相同(equals),但是不等于他们俩是一个人。你只要记住equals,==就不用记了。

    术语来讲的区别:

    1、==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同

    2、==是指对内存地址进行比较 equals()是对字符串的内容进行比较3.==指引用是否相同 equals()指的是值是否相同

    31、如何判断一个对象是否存活

    判断一个对象是否存活有两种方法:

    **1、**引用计数法

    所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象时,就将计数器加一,引用失效时,计数器就减一。当一个对象的引用计数器为零时,说明此对象没有被引用,也就是“死对象”,将会被垃圾回收、

    引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象 A 引用对象 B,对象 B 又引用者对象 A,那么此时 A、B 对象的引用计数器都不为零,也就造成无法完成垃圾回收,所以主流的虚拟机都没有采用这种算法。

    **2、**可达性算法(引用链法)

    该算法的思想是:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到 GC Roots 没有任何引用链相连时,则说明此对象不可用。

    在 Java 中可以作为 GC Roots 的对象有以下几种:

    **1、**虚拟机栈中引用的对象

    **2、**方法区类静态属性引用的对象

    **3、**方法区常量池引用的对象

    **4、**本地方法栈JNI引用的对象

    虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象比不一定会被回收。当一个对象不可达 GC Root 时,这个对象并不会立马被回收,而是出于一个死缓的阶段,若要被真正的回收需要经历两次标记、

    如果对象在可达性分析中没有与 GC Root 的引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行 finalize() 方法。当对象没有覆盖 finalize() 方法或者已被虚拟机调用过,那么就认为是没必要的。 如果该对象有必要执行 finalize() 方法,那么这个对象将会放在一个称为 F-Queue 的对队列中,虚拟机会触发一个 Finalize() 线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果 finalize() 执行缓慢或者发生了死锁,那么就会造成 F-Queue 队列一直等待,造成了内存回收系统的崩溃。GC 对处于 F-Queue 中的对象进行第二次被标记,这时,该对象将被移除” 即将回收” 集合,等待回收。

    32、Int与integer的区别

    Integer是int的包装类型。

    Int的默认值是0,integer的默认值是null

    33、Servlet的生命周期?

    **1、**加载:判断servlet实例是否存在,如果不存在,就加载serlvet

    **2、**实例化:

    **3、**初始化

    4、服务

    5、销毁

    34、怎么唤醒一个阻塞的线程

    如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它;如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。

    35、虚拟DOM的优劣如何?

    优点:

    **1、**保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限

    **2、**无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率

    **3、**跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等

    缺点:

    无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化

    36、双亲委派模型是什么?

    类加载器具有等级制度但非继承关系,以组合的方式复用父加载器的功能。双亲委派模型要求除了顶层的启动类加载器外,其余类加载器都应该有自己的父加载器。

    一个类加载器收到了类加载请求,它不会自己去尝试加载,而将该请求委派给父加载器,每层的类加载器都是如此,因此所有加载请求最终都应该传送到启动类加载器,只有当父加载器反馈无法完成请求时,子加载器才会尝试。

    类跟随它的加载器一起具备了有优先级的层次关系,确保某个类在各个类加载器环境中都是同一个,保证程序的稳定性。

    37、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

    Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化,其语法看起来挺诡异的,如下所示。

    /  * 扑克类(一副扑克)  * @author 骆昊  *  */
    public class Poker {
        private static String[] suites = {
            "黑桃", "红桃", "草花", "方块"
        };
        private static int[] faces = {
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
        };
        private Card[] cards;
        /      * 构造器      *       */
        public Poker() {
            cards = new Card[52];
            for (int i = 0; i < suites.length; i++) {
                for (int j = 0; j < faces.length; j++) {
                    cards[i * 13 + j] = new Card(suites[i], faces[j]);
                }
            }
        }
        /      * 洗牌 (随机乱序)      *       */
        public void shuffle() {
            for (int i = 0, len = cards.length; i < len; i++) {
                int index = (int)(Math.random() * len);
                Card temp = cards[index];
                cards[index] = cards[i];
                cards[i] = temp;
            }
        }
        /      * 发牌      * @param index 发牌的位置      *       */
        public Card deal(int index) {
            return cards[index];
        }
        /      * 卡片类(一张扑克)      * [内部类]      * @author 骆昊      *      */
        public class Card {
            private String suite; // 花色         private int face;       // 点数         
     public Card(String suite, int face) {             this.suite = suite;           
      this.face = face;         }          @Override       
    
      public String toString() {             String faceStr = "";             switch(face) {             case 1: faceStr = "A"; break;             case 11: faceStr = "J"; break;             case 12: faceStr = "Q"; break;             case 13: faceStr = "K"; break;             default: faceStr = String.valueOf(face);             }             return suite + faceStr;         }     } }
            测试代码:
            class PokerTest {
                public static void main(String[] args) {
                    Poker poker = new Poker();
                    poker.shuffle();
                    // 洗牌         Poker.Card c1 = poker.deal(0);  // 发第一张牌       
      // 对于非静态内部类Card         // 只有通过其外部类Poker对象才能创建Card对象     
        Poker.Card c2 = poker.new Card("红心", 1);    // 自己创建一张牌        
      System.out.println(c1);     // 洗牌后的第一张         System.out.println(c2);  
       // 打印: 红心A     } }
    

    面试题 - 下面的代码哪些地方会产生编译错误?

    class Outer { class Inner {} public static void foo() { new Inner(); } public void bar() { new Inner(); } public static void main(String[] args) { new Inner(); } }

    注意:Java中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做:

    new Outer().new Inner();

    38、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?

    **1、**不会,在下一个垃圾回调周期中,这个对象将是被可回收的。

    **2、**也就是说并不会立即被垃圾收集器立刻回收,而是在下一次垃圾回收时才会释放其占用的内存。

    39、JVM 出现 fullGC 很频繁,怎么去线上排查问题

    这题就依据full GC的触发条件来做:

    **1、**如果有perm gen的话(jdk1.8就没了),要给perm gen分配空间,但没有足够的空间时,会触发full gc。

    **2、**所以看看是不是perm gen区的值设置得太小了。

    3、System.gc()方法的调用

    **4、**这个一般没人去调用吧~~~

    **5、**当统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间,则会触发full gc(这就可以从多个角度上看了)

    **6、**是不是频繁创建了大对象(也有可能eden区设置过小)(大对象直接分配在老年代中,导致老年代空间不足—>从而频繁gc)

    **7、**是不是老年代的空间设置过小了(Minor GC几个对象就大于老年代的剩余空间了)

    40、JVM 内存区域

    JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA 堆、方法区】、直接内存。

    线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 Hotspot VM 内, 每个线程都与操作系统的本地线程直接映射, 因此这部分内存区域的存/否跟随本地线程的生/死对应)。

    线程共享区域随虚拟机的启动/关闭而创建/销毁。

    直接内存并不是 JVM 运行时数据区的一部分, 但也会被频繁的使用: 在 JDK 1.4 引入的 NIO 提供了基于Channel与 Buffer的IO方式, 它可以使用Native函数库直接分配堆外内存, 然后使用DirectByteBuffer 对象作为这块内存的引用进行操作(详见: Java I/O 扩展), 这样就避免了在 Java堆和 Native 堆中来回复制数据, 因此在一些场景中可以显著提高性能。

    更多 Java 面试题 70 道

    01、如何判断一个对象是否存活

    02、Int与integer的区别

    03、Servlet的生命周期?

    04、怎么唤醒一个阻塞的线程

    05、虚拟DOM的优劣如何?

    06、双亲委派模型是什么?

    07、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

    08、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?

    09、JVM 出现 fullGC 很频繁,怎么去线上排查问题

    10、JVM 内存区域

    11、Parallel Old 收集器(多线程标记整理算法)

    12、对象分配内存是否线程安全?

    13、当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

    14、Serial 与 Parallel GC 之间的不同之处?

    15、为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?

    16、redux异步中间件之间的优劣?

    17、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?

    18、Hibernate中Session的load和get方法的区别是什么?

    19、说一下堆内存中对象的分配的基本策略

    20、Java 中如何将字符串转换为整数?

    21、讲讲什么情况下会出现内存溢出,内存泄漏?

    22、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

    23、线程与进程的区别?

    24、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?

    25、用代码演示三种代理

    26、stackoverflow错误,permgen space错误

    27、分代收集算法

    28、同步方法和同步块,哪个是更好的选择?

    29、Java 中的编译期常量是什么?使用它又什么风险?

    30、Java死锁以及如何避免?

    31、String 属于基础的数据类型吗?

    32、如何实现对象克隆?

    33、Java最顶级的父类是哪个?

    34、如何通过反射创建对象?

    35、Java 中堆和栈有什么区别?

    36、volatile 能使得一个非原子操作变成原子操作吗?

    37、为什么选择使用框架而不是原生?

    38、你能写出一个正则表达式来判断一个字符串是否是一个数字吗?

    39、运行时栈帧包含哪些结构?

    40、什么是Java程序的主类?应用程序和小程序的主类有何不同?

    41、volatile 关键字的作用

    42、Java 中用到的线程调度算法是什么?

    43、简单描述一下(分代)垃圾回收的过程

    44、什么是可重入锁(ReentrantLock)?

    45、线程池有什么优点?

    46、你有哪些手段来排查 OOM 的问题?

    47、什么是线程异步?什么是线程同步?

    48、Java 中,受检查异常 和 不受检查异常的区别?

    49、OOP 中的 组合、聚合和关联有什么区别?

    50、Java网络编程有几种?

    51、js如何实现页面刷新呢?

    52、什么是线程池?

    53、如何实现 Array 和 List 之间的转换?

    54、普通类和抽象类有哪些区别?

    55、为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object 类里?

    56、遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?

    57、[String str="i"与 String str=new String(“i”)一样吗?](https://link.zhihu.com/target=https%3A//gitee.com/souyunku/DevBooks/blob/master/docs/Java/Java%25E6%259C%2580%25E6%2596%25B0%25E9%259D%25A2%25E8%25AF%2595%25E9%25A2%2598%25E5%258F%258A%25E7%25AD%2594%25E6%25A1%2588%25E9%2599%2584%25E7%25AD%2594%25E6%25A1%2588%25E6%25B1%2587%25E6%2580%25BB.md%237string-str%3D%2522i%2522%25E4%25B8%258E-string-str%3Dnew-string%2522i%2522%25E4%25B8%2580%25E6%25A0%25B7%25E5%2590%2597 "String str=“i"与 String str=new String(“i”)一样吗?”)

    58、用过ConcurrentHashMap,讲一下他和HashTable的不同之处?

    59、线程的基本状态以及状态之间的关系?

    60、线程池中 submit() 和 execute() 方法有什么区别?

    61、在java中守护线程和本地线程区别?

    62、CMS分为哪几个阶段?

    03、抽象的关键字是什么?

    64、如何判断对象可以被回收

    65、如何通过反射调用对象的方法?

    66、如何进行单元测试

    67、什么情况下会发生栈内存溢出?

    68、什么是Hash算法

    69、什么是上下文切换?

    70、列举一些你知道的打破双亲委派机制的例子。为什么要打破?

    这套Java面试题大全,希望对大家有帮助哈~

    博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的

    展开全文
  • java面试笔试资料java笔试题大集合及答案题库java笔试题汇总资料188个合集 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx ...
  • JAVA面试题及答案整理(最新版)

    千次阅读 2022-04-19 14:56:04
    这些Java技术栈整理成册(包括:VM,JAVA集合,JAVA多线程并发,JAVA基础,Spring原理,微服务,Netty与RPC,网络,日志,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,...

    这些Java技术栈整理成册(包括:VM,JAVA集合,JAVA多线程并发,JAVA基础,Spring原理,微服务,Netty与RPC,网络,日志,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存,Hadoop,Spark,Storm,YARN,机器学习,云计算),对你的面试大有帮助,让你offer到手,高薪也有!

    JVM

    1. 线程

    2. JVM内存区域

    3. JVM运行时内存

    4. 垃圾回收与算法

    5. JAVA四种引用类型

    6. GC分代收集算法V

    7. 分区收集算法

    8. GC垃圾收集器

    JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和 一个存储方法域,JVM是运行在操作系统之上的,它与硬件没有直接的交互。

    JAVA多线程并发

    1. JAVA并发知识库

    2. JAVA线程实现/创建方式

    3. 4种线程池

    4. 线程生命周期(状态)

    5. 终止线程4种方式

    6. sleep与wait区别

    7. start与run区别

    8. JAVA后台线程

    9. JAVA锁

    10. 线程基本方法

    11. 线程上下文切换

    12. 同步锁与死锁

    13. 线程池原理

    14. JAVA阻塞队列原理

    15. volatile关键字的作用(变量可见性、禁止重排序

    16. 如何在两个线程之间共享数据

    17. ThreadLocal作用(线程本地存储)

    JAVA基础

    1. JAVA异常分类及处理

    2. JAVA反射

    3. JAVA注解

    4. JAVA内部类

    5. JAVA泛型

    6. JAVA序列化(创建可复用的Java对象)

    7. JAVA复制

    Spring原理

    1. Spring特点

    2. Spring核心组件

    3. Spring常用模块

    4. Spring 主要包

    5. Spring 常用注解

    6. Spring 第三方结合

    7. SpringIOC原理

    8. Spring APO厚理

    9. Spring MVC原理

    10. Spring Boot原理

    11. JPA原理

    12. Mybatis缓存

    13. Tomcat架构

    微服务

    1. 服务注册发现

    2. API网关

    3. 配置中心

    4. 事件调度(kafka)

    5. 服务跟踪(starter-sleuth)

    6. 服务熔断(Hystrix)

    7. API管理

    Netty与RPC

    1. Netty原理

    2. Netty高性能

    3. Netty RPC实现

    4. RMI实现方式

    5. Protoclol Buffer

    6. Thrift

    网络

    1. 网络7层架构

    2. TCP/IP原理

    3. TCP三次握手/四次挥手

    4. HTTP原理

    5. CDN原理

    Zookeeper

    1. Zookeeper概念

    2. Zookeeper角色

    3. Zookeeper工作原理(原子广播)

    4. Znode有四种形式的目录节点

    Kafka

    1. Kafka概念

    2. Kafka数据存储设计

    3. 生产者设计

    4. 消费者设计

    RabbitMQ

    1. 概念

    2. RabbitMQ架构

    3. Exchange类型

    Hbase

    1. 概念

    2. 列式存储

    3. Hbase核心概念

    4. Hbase核心架构

    5. Hbase的逻辑

    6. HBase vs Cassandra

    MongoDB

    1. 概念

    2. 特点

    Cassandra

    1. 概念

    2. 数据模型

    3. Cassandra- 致Hash和虚拟节点

    4. Gossip协议

    5. 数据复制

    6. 数据写请求和协调者

    7. 数据读请求和后台修复

    8. 数据存储(CommitLog、 MemTable. SSTable

    9. 级索引(对要索引的value摘要,生成RowKey)

    24种设计模式

    1. 设计原则

    2. 方法模式

    3. 抽象工厂模式

    4. 单例模式

    5. 建造者模式

    6. 原型模式

    7. 适配器模式

    8. 装饰器模式

    9. 代理模式

    10. 外观模式

    11. 桥接模式

    12. 组合模式

    13. 享元模式

    14. 策略模式

    15. 模板方法模式

    16. 观察者模式

    17. 迭代子模式

    18. 责任链模式

    19. 命令模式

    20. 备忘录模式

    21. 状态模式

    22. 访问者模式

    23. 中介者模式

    24. 解释器模式

    负裁均衡

    1. 四层负载均衡vs七层负载均衡

    2. 负裁均衡算法/策略

    3. LVS

    4. Keepalive

    5. Nginx反向代理负载均衡

    6. HAProxy

    数据库

    1. 存储引擎

    2. 索引

    3. 数据库三范式

    4. 数据库是事务

    5. 存储过程(特定功能的SQL语句集)

    6. 触发器(-段能自动执行的程序)

    7. 数据库并发策略

    8. 数据库锁

    9. 基于Redis分布式锁

    10. 分区分表

    11. 两阶段提交协议

    12. 三阶段提交协议.

    13. 柔性事务

    14. CAP

    一致性算法

    1. Paxos

    2. Zab

    3. Raft

    4. NWR

    5. Gossip

    6. 一致性Hash

    JAVA算法

    1. 二分查找

    2. 冒泡排序算法

    3. 插入排序算法

    4. 快速排序算法

    5. 希尔排序算法

    6. 归并排序算法

    7. 桶排序算法

    8. 基数排序算法

    9. 剪枝算法

    10. 回溯算法

    11. 最短路径算法

    12. 最大子数组算法

    13. 最长公共子序算法

    14. 最小生成树算法

    数据结构

    1. 栈(stack)

    2. 队列(queue)

    3. 链表(Link)

    4. 散列表(Hash Table)

    5. 排序二叉树

    6. 红黑树

    7. B-TREE

    8. 位图

    加密算法

    1. AES

    2. RSA

    3. CRC

    4. MD5

    分布式缓存

    1. 缓存雪崩

    2. 缓存穿透

    3. 缓存预热

    4. 缓存更新

    5. 缓存降级

    Hadoop

    1. 概念

    2. HDFS

    3. MapReduce

    4. Hadoop MapReduce作业的生命周期

    Spark

    1. 概念

    2. 核心架构

    3. 核心组件

    4. SPARK编程模型

    5. SPARK计算模型

    6. SPARK运行流程

    7. SPARK RDD流程

    8. SPARK RDD

    机器学习

    1. 决策树

    2. 随机森林算法

    3. 逻辑回归

    4. SVM

    5. 朴素贝叶斯

    6. K最近邻算法

    7. K均值算法

    8. Adaboost算法

    9. 神经网络

    10. 马尔可夫

    展开全文
  • Java面试题及答案整理(2020最新版),详细汇总资料。
  • Java面试题及答案(2022版),适用于应届生和有工作经验的程序员,每道都是认真筛选出的高频面试题,助力大家能找到满意的工作!B/S(Browser/Server),浏览器/服务器程序;C/S(Client/Server),客户端/服务端,桌面应用...
  • 有些Java面试题答案是我自己总结的,也有些Java面试题及答案是在网上搜集整理的。这些高级Java面试题及答案难免会存在一些错误,这些面试题答案难免会存在一些错误,仅供大家参考。如果发现错误还望大家多多包涵,...
  • Java 最常见的 208 道面试题》的答案已经全部更新完了,有些答案是团长自己总结的,也有些答案是在网上搜集整理的。这些答案难免会存在一些错误,仅供大家参考。如果发现错误还望大家多多包涵,不吝赐教,谢谢~ ...
  • 这是我收集的10道高级Java面试问题列表。这些问题主要来自 Java 核心部分 ,不涉及 Java EE 相关问题。你可能知道这些棘手的 Java 问题的答案,或者觉得这些不足以挑战你的 Java 知识,但这些问题都是容易在各种 Java...
  • Java面试题及答案整理(2020最新版) 《Java 最常见的 208 道面试题》的答案已经全部更新完了,有些答案是团长自己总结的,也有些答案是在网上搜集整理的。这些答案难免会存在一些错误,仅供大家参考。如果发现错误...
  • 有很多小伙伴为社招或跳槽做准备,最近小编也常常在刷面试题,发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~ 博主已将以下这些面试题整理成了一个...
  • 最新、最全的 Java 面试题,题目涉及 Java 基础、集合、多线程、IO、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等。 题库共 600+ 道,带全部答案,非常齐全! Java 基础 1、面向对象编程...
  • JAVA面试题大全(含答案)JAVA面试题大全(含答案)JAVA面试题大全(含答案)
  • 2019年最新Java面试题及答案整理
  • 最新整理Java面试题,详细面试题完整答案,资料详细,查漏补缺不断完善和扩充自己 java 技术栈, java 面试官 具体面试题,觉得重要的东西总结了一下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,365
精华内容 18,146
关键字:

java面试题及答案整理