logo资料库

一份牛逼的JAVA面试知识点总结.pdf

第1页 / 共90页
第2页 / 共90页
第3页 / 共90页
第4页 / 共90页
第5页 / 共90页
第6页 / 共90页
第7页 / 共90页
第8页 / 共90页
资料共90页,剩余部分请下载后查看
---- Hyman com.thornBird V1.0 摘录 Java_SE Java_EE 持久化 前端 工具环境 星辰大海 Java_SE JDK && JRE && JVM JDK:Java Development Kit,Java 开发包,Java 开发工具,包含JRE、编译器、调试器、 DOC等; JRE:Java RunTime Envirment,Java 运行环境; JVM:java virtual machine,Java 虚拟机,类装载器、字节码校验器、解释器三个功能,是 Java 跨平台性的关键; 执行 Java 文件流程 java 源程序 *.java ---- java编译器 ---- 转换成字节码*.class 文件 ---- 交给 JVM; JVM 共做三个步骤: 类装载器 字节码校验器 解释器 交给操作系统平台进行显示; Java 程序执行过程 java源文件 ---- 编译生成字节码文件(.class) ---- JVM(加载、校验、解释); 能否在加载类的时候,对字节码进行修改? 使用 Java 探针技术(javaagent),运行在 main 方法之前的拦截器,它内定的方法名 叫 premain,通过配置 -javaagent VM 参数实现; JVM调优,堆栈区内置内容?有哪些虚拟机实现?不同的垃圾回收器怎么工作的? JVM 内存划分;
类加载器(ClassLoader) 运行时数据区(Runtime Data Area) 程序计数器(Program Counter Register):当前线程所执行的字节码的行 号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需 要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能, 都需要依赖这个计数器来完成; Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操 作数栈、动态链接、方法出口等信息; 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过 虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务 的; Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享 的,几乎所有的对象实例都在这里分配内存; 方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变 量、即时编译后的代码等数据 执行引擎(Execution Engine) 本地库接口(Native Interface) 组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码, 运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只 是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定 的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再 交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能; 堆栈的区别? 功能方面:堆是用来存放对象的,栈是用来执行程序的; 共享性:堆是线程共享的,栈是线程私有的;
空间大小:堆大小远远大于栈; JVM内存大小 = 年轻代大小 + 年老代大小 + 持久代大小 年轻代:所有新生成的对象首先都是放在年轻代; 伊甸园、存活区(from、to) 老年代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代 中。因此,可以认为年老代中存放的都是一些生命周期较长的对象; 持久代:用于存放静态文件; 垃圾回收流程 新的对象保存在伊甸园,伊甸园不足,则出发年轻代垃圾回收; 再判断伊甸园内存是否足够,不够查看存活区,如果存活区足够,则将伊甸园部分 对象保存在存活区,自己留在伊甸园; 如果存活区内存不够,则查看老年代内存是否足够,足够则依次迁移存活区到老年 代,伊甸园到存活区,自己留在伊甸园; 如果老年代内存都不足,则进行全局gc,清理完之后依然不足,则抛出 outofmemory异常 ---- 这个时候需要根据异常的信息进行相应的修改jvm参数; 垃圾收集算法 标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除 垃圾碎片; 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对 象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不 高,只有原来的一半; 标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除 掉端边界以外的内存; 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代, 新生代基本采用复制算法,老年代采用标记整理算法; JVM 有哪些垃圾回收器? 新生代回收器 Serial:最早的单线程串行垃圾回收器; ParNew:是 Serial 的多线程版本; Parallel:使用的是复制的内存回收算法; 老年代回收器 Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案; Parallel Old:使用的是标记-整理的内存回收算法; CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统; 整堆回收器 G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选 项; 常用配置
堆设置(操作系统32/64限制、虚拟内存限制、可用物理内存限制) java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:NewRatio=4 - XX:SurvivorRatio=4 -XX:MaxPermSize=16m - XX:MaxTenuringThreshold=0 -Xms:初始堆大小; -Xmx:最大堆大小; -XX:NewSize=n:设置年轻代大小; -XX:NewRatio=n:设置年轻代和年老代的比值,如:为3,表示年轻代与年老 代比值为1:3,年轻代占整个年轻代年老代和的1/4; -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值,注意 Survivor区有两个,如:3,表示Eden:Survivor=3:2,一个Survivor区占 整个年轻代的1/5; -XX:MaxPermSize=n:设置持久代大小; 收集器设置 串行(吃完饭--接电话)、并发(吃饭--接电话--吃饭)、并行(边吃饭边接 电话) 收集器:Gc收集器(多线程、单线程 | 新生代、老年代、G1) 响应时间优先 java -Xmx3550m -Xms3550m -Xmn2g -Xss128k - XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC - XX:+UseParNewGC -XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这 个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代 大小最好用-Xmn设置。 -XX:+UseParNewGC:设置年轻代为并行收集。可与CMS收集同时使用。 JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。 java -Xmx3550m -Xms3550m -Xmn2g -Xss128k - XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进 行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降 低。此值设置运行多少次GC以后对内存空间进行压缩、整理。 -XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能 会影响性能,但是可以消除碎片 吞吐量优先 java -Xmx3800m -Xms3800m -Xmn2g -Xss128k - XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代 有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收 集;
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少 个线程一起进行垃圾回收。此值最好配置与处理器数目相等; java -Xmx3550m -Xms3550m -Xmn2g -Xss128k - XX:+UseParallelGC -XX:ParallelGCThreads=20 - XX:+UseParallelOldGC -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0 支持对年老代并行收集; java -Xmx3550m -Xms3550m -Xmn2g -Xss128k - XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如 果无法满足此时间,JVM会自动调整年轻代大小,以满足此值; java -Xmx3550m -Xms3550m -Xmn2g -Xss128k - XX:+UseParallelGC -XX:MaxGCPauseMillis=100 - XX:+UseAdaptiveSizePolicy -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择 年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应 时间或者收集频率等,此值建议使用并行收集器时,一直打开; -XX:+UseSerialGC:设置串行收集器; -XX:+UseParallelGC:设置并行收集器; -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数,并行 收集线程数; -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间; -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公 式为1/(1+n); -XX:+UseParalledlOldGC:设置并行年老代收集器; -XX:+UseConcMarkSweepGC:设置并发收集器; -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况; -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集 时,使用的CPU数,并行收集线程数; 辅助信息 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename 队列和栈是什么?有什么区别? 队列和栈都是被用来预存储数据的; 队列允许先进先出检索元素,但也有例外的情况,Deque 接口允许从两端检索元素; 栈和队列很相似,但它运行对元素进行后进先出进行检索; 什么是双亲委派模型?
在介绍双亲委派模型之前先说下类加载器。对于任意一个类,都需要由加载它的类加载 器和这个类本身一同确立在 JVM 中的唯一性,每一个类加载器,都有一个独立的类名 称空间。类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转 化为 class 对象; 类加载器分类: 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载 Java_HOME/lib/目录中的,或者被 -Xbootclasspath 参数所指定的路径中并且被 虚拟机识别的类库; 其他类加载器: 扩展类加载器(Extension ClassLoader):负责加载\lib\ext目录或Java. ext. dirs 系统变量指定的路径中的所有类库; 应用程序类加载器(Application ClassLoader):负责加载用户类路径 (classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我 们没有自定义类加载器默认就是用这个加载器; 双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个 类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有 的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它 的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类; 怎么判断对象是否可以被回收? 引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时 计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题; 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象 到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的; Java 特征 面向对象:万物皆对象; 封装 继承 多态 封装是按照信息屏蔽的原则,把对象的属性和操作结合在一起,构成一个独立的对象,外 部对象不能直接操作对象的属性,只能使用对象提供服务,隐藏了属性、方法实现细节的 过程; 体现了系统间的松散耦合关系,提高了系统的独立性; 提高了软件的重用性; 为了实现类与类之间代码上的共享,抽取对象之间共同的属性和行为; 父类的构造方法不会被继承; 子类调父类方法:构造器中 ---- super();普通方法中 ---- super.父类方法(); 终态类不能被继承; java中是单继承,多实现,一个类不能继承多个父类; 重写:发生在继承关系下的不同类中,要求方法名、参数列表和返回值类型必须相同;访 问修饰符要向上兼容;子类抛出的异常必须大于等于父类抛出的异常;
重载:发生在同一个类中,方法名相同,但是参数列表不同; 动态绑定:父类的引用指向子类的对象;接口的引用指向实现类的对象; 其他特点 简单、多线程、分布式、可移植、健壮性、解释性、安全(Java 程序都运行在虚似机 上,这样能够防止底层操作系统受到损害)、垃圾回收; What is Polymorphism in Object Oriented Programming? Please provide a program example that uses the concept of Polymorphism. ---- 什么是多态?请提供一个多态程 序示例; What are the advantages of encapsulation? ---- 封装的优点; Please provide an program example that uses the concept of inheritance. ---- 请提供 一个继承程序实例; System.out 和 System.in System.in:标准输入流,此流已打开并准备提供输入数据,通常对应键盘输入; System.out:标准输出流,此流已打开并准备接受输出数据,通常,此流对应于显示器输 出; Java 基本数据类型 ---- 四类八种,全部小写,是关键字; 整形:字节型 byte 占 8bit、短整形 short 占 2B、整形 int 占 4B、长整形 long 占 8B; 浮点型:单精度 float 占 4B、双精度 double 占 8B; 字符型:char,采用 Unicode 编码,每个字符占 2B; 逻辑型:布尔型 boolean,占 1bit; Java 中都有哪些引用类型? 强引用:发生 gc 的时候不会被回收; 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收; 弱引用:有用但不是必须的对象,在下一次GC时会被回收; 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引 用,虚引用的用途是在 gc 时返回一个通知; 基本数据类型转换 java 默认的整形和浮点型为 int 和 double,在程序中涉及到一些转换,那么需要在数值后面 加上转换声明的第一个字母,举例:float f = 2f + 3.3; 自动转换:float i = 2.2f; ---- 一般遵循规则:从低级到高级转换(范围大小); 强制转换:int i = (int)2.3; 三目运算中数据转换 1 1 2 3 4 // boolean -- 1byte, char -- 2byte, 0(short:0-65535) -- 2byte, int -- 4byte // 三目运算中自动转换类型,都打印x,但转换类型后结果为b、98、98、98 char x = 'b'; int i = 0;
5 6 7 8 System.out.println(true ? x : 0); System.out.println(true ? x : 65536); System.out.println(true ? x : 111111111); System.out.println(false ? i: x); 2 算术表达式优先级 算术运算符:+ 、 - 、 * 、 / 、 % 、 ++ 、 -- ; 关系运算符: < 、 > 、 >= 、 = 、 == 、 != ; 逻辑运算符:与 &&、或 | | 、非 !; 位运算符:& 、 | 、 ^ 、 ~ 、 >> 、 << 、 >>> ; 三目运算符(条件运算符):x ? y : z ; 赋值运算符:=; 基本运算符 > 关系运算符 > 逻辑运算符 > 条件运算符 > 赋值运算符,其中逻辑运算符中 的!运算大于基本运算符; 5%3、-5%3、5%-3、-5%-3 2、-2、2、-2,符号看前面; euqals 和 == 的区别 ==:基本数据类型比较值,String 比较值和地址; equals:String比较值,引用型对象比较值和地址; int i = 1; int j = 1; String a = "hello"; String b = "hello"; ---- 产生一个字符串对象,在常量池; String d = new String("hello"); String d = new String("hello"); ---- 产生了两个字符串对 象,常量池一个,堆中new了一个; i == j ---- true ---- 基本数据类型 == 比较值; a == b ---- true ---- a、b 指向常量池同样的地址,值相同; a == c ---- false ---- c 在堆中 new 了一个,地址不同; c == d ---- false ---- c、d 在堆中new的字符串对象,地址不同; a.equals(b) ---- true ---- String 的 equals 比较值; 两个对象的 hashCode() 相同,则 equals() 也一定为 true? hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相 等; String、StringBuffer、StringBuilder String:定长; StringBuffer:不定长、线程安全; StringBuilder:不定长,线程不安全; for、while、do while 三种循环的用法
分享到:
收藏