---- 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 三种循环的用法