[常见java八股]java常见面试题
- ThreadLocal 是什么? 作用?原理?
ThreadLocal类允许每个线程绑定自己的值,拥有自己的本地变量。创建一个ThreadLocal变量时,每个线程都会拥有一个独立的副本,通过get与set方法访问这个副本,来解决线程安全的问题
其本质是,每个线程依靠维护threadlocalmap来存放变量 键是threadlocal,值是要存的数据对象,通过getmap()方法来获取对应的值
key是弱引用 value是强引用 垃圾回收会回收没有指向的threadlocal实例 使得key为空 但是threadlocalmap在线程池中仍然存在 value无法被回收 需要手动释放remove
- 线程池 怎么理解?怎么用?哪些参数?
线程池是存放一堆线程的资源池,主要为了防止每次都去获取资源带来的消耗,提高资源利用率。可以通过ThreadPoolExecutor构造器来创建,最主要的三个参数:核心线程数、最大线程数、任务队列。来新任务时,先塞核心线程,再塞进任务队列,最后塞进非核心线程,直到全满了再采用拒绝策略。
拒绝策略包括拒绝新任务、丢弃新任务、丢弃最早的没处理任务、自己解决(执行者caller自己的线程来处理任务,会阻塞主进程) 而任务队列又分为有界阻塞队列(大小为max_value,队列不可能放满)、同步队列(队列容量为0,来一个处理一个,可能会导致创建大量线程)还有延迟队列(按照延迟的长短作为优先级(堆)考虑处理,满了就扩容0.5倍,直到max_value)。
关于核心线程数的设定 如果是cpu密集型就设定为N+1(万一出现意外,cpu闲了就可以用多出来的那1个线程来处理),IO密集型就设置为2N(系统在处理IO的时候不用cpu,可以用来处理线程的任务)
- 谈一谈GC机制?
java的垃圾回收主要针对堆内存的对象分配与回收,回收不再被引用的对象。
堆内存主要有三部分(新生代(Eden+S0+S1) 老生代、永久代/元空间),Eden区满了就进行一次Minor GC(Young GC) 如果能存活就进入Survivor空间(S0/S1区),并设定年龄为1,每经历一次MinorGC/YongGC就年龄+1,直到15岁(默认)进入老生代,大对象(字符串等)可以直接进入老生代,FullGC则是回收整合堆的内存。
可以通过引用计数法(被引用就+1,引用失效就-1)和可达性分析算法(以GC Roots(虚拟机栈中的对象/本地方法栈的对象)为根,向下搜索,能够被引用的对象就不是垃圾)来判断对象能否存活。
垃圾回收算法包括:标记-清除法(老生代)、标记-整理法(老生代)、复制法(新生代)、分代收集法。
常见垃圾回收器包括:Serial(串行)收集器、ParNew(前者的并行版)收集器、CMS(并发)收集器(追求最短停顿,GC线程与用户线程同时工作,依靠标记-清除法) 、G1收集器(并行+并发、停顿可预测、分代混合收集、基于分区整合),其中G1收集器是jdk7默认收集器,将堆划分为多个小区域,优先选择回收价值最大的区域,整体基于“标记-整理”算法,局部来看是基于“标记-复制”(两个区域之间)算法实现,适用于多核心大内存的服务器。
- Java内存结构与java内存模型(JMM)?
JVM 内存结构定义运行时如何分区存储数据,JMM主要涉及并发编程,决定了线程和主内存之间的关系。
关于JMM:主要解决并发编程中的可见性、原子性和有序性问题,主内存存放实例对象,本地内存存储线程的共享变量副本,JMM遵从happens-before原则,定义了各个操作之间的执行顺序,确保一个操作的结果对其他操作的可见性。
关于java内存结构/区域:JVM虚拟机在运行时将内存划分成不同区域,包括:
(私有)程序计数器用来控制代码流程、恢复上下文切换;
(私有)虚拟机栈负责java的方法调用,由栈帧组成,包含局部变量表、动态链接、操作数栈和方法返回地址,常见两种错误:StackOverflowError(内存大小不能动态拓展时,方法调用深度超过虚拟机栈的最大深度)与OutOfMemoryError(内存大小可以动态拓展时,无法申请足够的内存空间);
(私有)本地方法栈负责 Native 方法服务,类似于虚拟机栈,负责其他语言的方法调用;
(共享)堆用来存储对象实例,详细见GC堆;内含字符串常量池是为了避免字符串的重复创建带来的内存消耗;
(共享)方法区/元空间并不真实存在(逻辑概念),用于存放静态变量、类信息、常量等,包含运行时常量池;
直接内存是为了提高 I/O 操作的效率,直接作用于操作系统的内存;
对象创建的过程:
1.类加载检查(检查是否加载过)、2.分配内存(指针碰撞/空闲列表)、3.初始化零值、4.设置对象头、5.执行初始化。
对象在内存中的分配:
1.对象头,包含标记字段(哈希码、CG年龄、锁信息等)和类型指针(通过这个指针来确定这个对象是哪个类的实例);
2.实例数据,真正存储的数据内容;
3.对齐填充字段,为了占满8字节的整数位。
- java三大特性与理解?java的特点?
java有封装、继承和多态的特点。封装使得对象的方法和属性被统一打包,通过一些方法接口提供给外部;继承使得子类可以继承父类的方法和属性,同时又可以自己拓展或者实现;多态则体现在重载和重写,重载是同一个方法名根据不同参数有不同的实现逻辑,重写是子类对父类方法的具体实现,也体现在动态多态,即允许父类的引用指向子类的实现。
java具有平台无关性、面向对象、支持多线程、支持自动垃圾回收。jvm允许了java可以跨平台运行,java经过编译后生成.class字节码文件,不同平台的jvm将字节码翻译成对应的机器码。区别于C++这种编译型语言(一次性编译成机器码)和python这种解释型语言(一句句边解释为机器码边执行)。
- 类加载机制?类的生命周期?
类的生命周期主要分为:加载-连接-初始化-使用-卸载,其中连接部分又分为验证-准备-解析;
类加载器分为:启动类加载器、扩展类加载器、应用程序类加载器、用户自定义类加载器;
双亲委派模型:先委托父加载器尝试加载,并依次向上递归,无法加载时,子加载器才会加载。这样是为了避免重复加载,保证安全性和一致性。
- java I/O模型?
java I/O模型分为BIO/NIO/AIO
- 从url输入到页面显示的过程?
1.浏览器通过DNS协议对请求的网址进行解析,得到服务器ip地址;
2.浏览器与服务器建立TCP连接,历经三次握手;
3.客户端向服务器发送http请求,包括请求行、请求头和请求体;
4.服务端处理发来的请求, 返回http相应信息,包括状态行、响应头和响应体;
5.浏览器解析HTML内容,然后构建 DOM 树、解析 CSS 和 JavaScript 文件等,最终渲染页面;
6.tcp四次挥手结束连接。
- https和http区别?怎么加密的?
区别在于http默认端口为80,https为443,且https通过ssl来保证加密安全,但也更耗费资源。
https遵从ssl协议来实现数据的加密,ssl协议在tcp协议之上,采用非对称加密,握手过程如下:
1.客户端向服务器发送请求,要求建立安全连接;
2.服务器响应并发送其数字证书,包含公钥和由证书颁发机构(CA)认证的签名信息;
3.客户端收到服务器的证书后,用公钥加密一个随机码发给服务端;
4.服务器收到后用私钥解密,得到会话密钥;
5.客户端和服务器通过会话密钥进行加密传输。
Comments NOTHING