夯实基础系列一:Java 基础总结 (2)

运算符优先级

点 () [] +(正) -(负) ++ -- ~ ! * / % +(加) -(减) << >> >>> < <= > >= instanceof == != & | ^ && || ?: = += -= *= /= %= &= |= ^= ~= <<= >>= >>>=

5. 字符串与数组 5.1 字符串创建与存储机制

常量池

new String("abc")创建1个或2个对象

5.2 ==、equals和hashCode区别

== 比较引用,内存

未覆盖,同==;比较内容

hashCode鉴定对象是否相等,返回整数

5.3 String,StringBuffer,StringBuilder

String:不可变,执行效率最低

StringBuffer:可修改,线程安全,效率较高

StringBuilder:可修改,线程不安全,效率最高

5.4 其他

数组初始化方式

length属性和length()方法

6. 异常处理 6.1 finally块执行时机

若try中有return,在return前

若try-finally或catch-finally中都有return,finally会覆盖

6.2 finally代码块不是一定会被执行

程序进入try之前出现异常

try中调用System.exit(0)

6.3 Error

严重错误,不可恢复

6.4 Exception

可恢复,编译器可捕捉

检查性异常

IO

SQL

运行时异常

JVM处理

NullPointException

ClassCastException

ArrayIndexOutOfBoundsException

出现异常后,一直往上层抛,直到遇到处理代码或最上层

多态。若先捕获基类,再捕获子类。子类处理代码将永远不会得到执行

7. Java平台与内存管理 7.1 Java平台与其他语言平台的区别

纯软件,包括JVM与JAVA API

JVM虚拟,不跨平台

7.2 JAVA代码的执行

代码编译为class:sun jdk 中javac

装载class:ClassLoader

执行class

解释执行

编译执行

client compiler

server compiler

7.3 java源码编译机制

词法分析器组件:Token流

语法分析器组件:语法树

语义分析器组件:注解语法树

将语法树中的名字、表达式等元素与变量、方法、类型等联系到一起

检查变量使用前是否已声明

推导泛型方法的类型参数

检查类型匹配性

进行常量折叠

检查所有语句都可到达

检查变量的确定性赋值

解除语法糖

将泛型JAVA转成普通Java

检查所有checked exception都被捕获或抛出

将含语法糖的语法树转成简单语法树eg:foreach,自动折叠

代码生成器组件:字节码

7.4 类加载机制

装载:全限定名+类加载器加载类

链接

校验

格式不符,抛VerifyError

加载引用的类失败:抛NoClassDefFoundError

准备:静态变量默认初始化

解析:属性、方法验证(可选)

初始化(不是类加载必须触发的)

静态初始化代码

构造器代码

静态属性初始化

触发时机

调用了new

反射调用了类中的方法

子类调用了初始化

JVM启动过程中指定的初始化类

Bootstrap Class Loader:$JAVA_HOME/jre/lib/rt.jar

Extension Class Loader:$JAVA_HOME/jre/lib/ext/*.jar

System Class Loader:$CLASSPATH

User Defined Class Loader

7.5 类执行机制

解释执行

JVM字节码为中间代码,由JVM在运行期对其解释并执行

invokestatic

invokevirtual

invokeinterface

invokespecial

基于栈

代码紧凑,体积小

线程创建后,产生PC和Stack

指令解释执行

栈顶缓存:栈顶值缓存在寄存器上

部分栈帧共享

编译执行

client compiler

轻量级,占内存少

方法内联

去虚拟化

冗余消除

server compiler

重量级,占内存多

逃逸分析是C2进行很多优化的基础

标量替换:用标量替换聚合量

栈上分配

若对象未逃逸,C2会选择在栈上直接创建Point对象实例,而不是在堆上

栈上分配更快速,对象易回收

同步消除:如果发现同步的对象未逃逸,那也没有同步的必要。C2会去掉同步代码块

7.6 内存空间

方法区:类信息,线程共享

对象实例+数组

分代管理

新生代

旧生代

本地方法栈:支持native方法,Sun JDK的实现中本地方法栈和JVM方法栈是同一个

PC寄存器:线程私有

JVM方法栈:线程私有

7.7 内存分配

Java对象,堆上分配,分配需加锁,开销大

当堆上空间不足-->GC-->仍不足-->抛OutOfMemory

Sun JDK 为新创建的线程在Eden上分配TLAB

多个小对象比大对象分配更高效

基于逃逸分析直接从栈上分配

7.8 内存回收

收集器

引用计数收集器

计数器增减有消耗

不适合循环引用

跟踪收集器

集中式管理

全局记录数据的引用状态

从根集合扫描对象,可能会造成应用程序暂停

三种实现算法

复制

适用于回收空间中存活对象较少

缺点:需要增加一块空的内存空间及进行对象的移动

标记-清除:会产生内存碎片

标记-压缩:不产生内存碎片

Sun JDK中可用GC

新生代

串行GC(Serial GC):复制算法

Minor GC

强软弱虚

并行回收GC(Parrallel Scavenge):扫描复制多线程

并行 GC(ParNew):配合旧生代 CMS

旧生代和持久代可用GC

串行:标记压缩+清除

并行:标记压缩

并发:CMS

标记:暂停

并发标记:恢复,轮询着色对象,以标记它们

重新标记:暂停

并发收集:恢复

CMS内存回收易产生碎片,但是它提供了整理碎片的功能

浮动垃圾:CMS回收时产生应该回收但要等到下次CMS才能被回收掉的对象

Full GC

对新生代旧生代及持久代都进行的GC

触发的四种情况

旧生代空间不足

持久代空间满

CMS GC出现promotion failed和concurrent mode failure

统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间

7.9 内存泄露

一个不再被程序使用的对象或变量还在内存中占有存储空间

符合垃圾回收标准

对象赋空值null

给对象赋予新值,重新分配了内存空间

泄露的两种情况

堆中申请的空间没有被释放

对象不再被使用,但仍然存活在内存中

泄露原因

静态集合类

各种连接

监听器

变量不合理的作用域

单例模式

8. 分布式Java应用 8.1 基于消息方式实现系统间的通信

TCP/IP+BIO

socket.setSoTimeOut()设置等待响应的超时时间

一连接一线程

缺点:无论连接是否真实,都要创建线程

BIO下服务器端所能支撑的连接数目有限

TCP/IP+NIO

Channel

SocketChannel:建立连接,监听事件,操作读写

ServerSocketChannel:监听端口,监听连接事件

Selector:获取是否要处理的事件

Buffer:存放处理的数据

NIO Reactor模式,通过注册感兴趣的事件及扫描是否有感兴趣的事件发生,从而做出相应的动作

多个请求,连接复用

只有在有真实的请求时,才会创建线程

一请求一线程

UDP/IP+BIO

DatagramSocket:负责监听端口,读写数据

DatagramPacket:作为数据流对象进行传输

UDP/IP+NIO

DatagramChannel:监听端口,进行读写

ByteBuffer:数据流传输

NIO好处:只在有流要读取或可写入流时才做出相应的IO操作,而不像BIO方式阻塞当前线程

8.2 基于远程调用方式实现系统间的通信

远程调用方式

系统间通信和系统内一样

让使用者感觉调用远程同调用本地一样

基于Java自身技术

RMI:客户端代理,stub,封装对象,序列化为流,TCP/IP BIO,Skeleton,反序列化,获取对象实例,调用

WebService

服务端的服务生成WSDL文件

将应用+WSDL文件放入HTTP服务器

借用Java辅助工具根据WSDL文件生成客户端stub代码

stub将产生的对象请求信息封装为标准化的SOAP格式数据,并发请求到服务器端

服端在接收到SOAP格式数据时进行转化,反射调用相应的Java类

SOAP优点支持跨语言,缺点对复杂对象结构难支持

8.3 基于开源框架

Spring RMI

9. 多线程 9.1 线程资源同步机制

JVM保证以下操作顺序

同一线程操作

对于main Memory 上的同一个变量的操作

对于加了锁的main Memory上的对象操作

为避免资源操作的脏数据问题,JVM提供了

synchronized

volatile

lock/unlock

目的是控制资源竞争

9.2 线程交互机制

基于Object的wait/notify/notifyAll

为避免假唤醒,需要double check

调用对象的wait-->wait sets--->释放锁--->其他线程notify---->wait sets---->执行此对象线程--->删除sets中此线程

基于JDK 5 并发包,支持线程交互

Semphore的acquire,release

Condition的await,signal

CountDownLatch的await和countDown

9.3 线程状态

New

Runnable

Running

Wait

TimedWait

Blocked

Terminated

9.4 sleep()与wait()方法的区别

sleep

暂停一段时间执行

Thread的静态方法

不释放锁

需要捕获异常

wait

使线程暂停执行

Object方法,用于线程间通信

释放锁

9.5 守护线程

后台提供服务

用户线程全部终止,只剩下守护线程时,JVM就会退出

调用start()之前,调用线程对象的setDaemon(true)

9.6 join

调用该方法的线程在执行完run()后,再执行join方法后面的代码

线程合并,实现同步功能

10. IO 10.1 流本质

数据传输

10.2 流分类

字节流:不使用缓存

字符流

码表映射

使用缓存

10.3 装饰者模式

运行时动态给对象增加额外的职责

是你还有你,一切拜托你

FilterInputStream

10.4 Java Socket

ServerSocket server = new ServerSocket(2000);

Socker socket = server.accept();

客户端:Socket socket = new Socket("localhost",2000);

10.5 NIO

Channel--Selector--Buffer

反应器模式

10.6 序列化

对象持久化方式

解决在对对象流进行读写操作时引发的问题

对象写进流里进行网络传输,保存到文件,数据库

10.7 如何实现序列化

实现Serializable接口

使用FileOutputStream来构造ObjectOutputStream对象

使用该对象的writeObject(obj)方法将对象写出

要恢复时,使用对应的输入流

10.8 序列化特点

一个类能被序列化,它的子类也能被序列化

static代表类成员,transient代表临时数据。均不能被序列化

序列化影响性能,需要才使用

需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中

序列化能实现深复制,即可以复制引用的对象

10.9 反序列化

将流转化为对象

UID最好自己定义。优点

提高程序运行效率。省去计算过程

提高程序不同平台兼容性。不同计算方式,反序列化失败

增强程序各个版本的可兼容性。加入新属性,默认UID变化

10.10 外部序列化

实现Externalizable接口控制

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdpxz.html