《OD面试》Java软件工程师 一、JVM自动内存管理机制 二、JVM虚拟机执行子系统 三、JVM程序编译及代码优化 四、JVM高效并发 五、String 六、Java集合框架 七、内存映射原理 十、数据库 十一、 JavaEE 九九、分布式

1. Java内存模型

1.1 由所有线程共享的数据区:

1.1.1 方法区(Method Area), Non-Heap(非堆)

用户存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

“永久代”,本质上两者并不等价。

这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。

当方法区无法满足内存分配需求时,将抛出OutOfMemoryError。

1.1.1.1 运行时常量池: 

常量池用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。

当常量池无法再申请到内存时,将抛出OutOfMemoryError。

1.1.2 堆(Heap) , GC堆(Garbage Collected Heap)

存放对象实例。

Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就想我们的磁盘空间一样。

可实现成固定大小的,也可以是可拓展的。当前主流的虚拟机都是按照可拓展来实现的。

-Xmx

-Xms

如果堆中没有内存完成实例分配,并且堆也无法再拓展时,将会抛出OutOfMemoryError。

新生代: Eden区,From Survivor区,To Survivor区 

老年代:

1.2 线程私有的数据区

1.2.1 虚拟机栈(VM Stack)

虚拟机栈是Java方法执行的内存模型: 每个方法被执行的时候,都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。

局部变量表: 编译期可知的各种基本数据类型、对象引用

1.2.2 本地方法栈(Native Method Stack)

本地方法栈为虚拟机使用导的Native方法服务。

本地方法栈区也会抛出*Error和OutofMemoryError异常。

1.2.3 程序计数器(Program Counter Register)

字节码解释器通过改变程序计数器的值来选取下一条需要执行的字节码指令。

Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储。

两种异常状况:

如果线程请求的栈深度大于虚拟机所允许的深度,将抛出*Error异常;

如果虚拟机栈可以动态拓展,当拓展时无法申请到足够的内存时会抛出OutofMemoryError异常。

1.3 直接内存

NIO, 通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。

1.4 对象访问

1.4.1 使用句柄

Java堆中划分出一块内存来作为句柄池,reference中存储的就是独享的句柄地址。

1.4.2 直接指针

reference中直接存储的就是对象地址。

Sun HotSport使用的是直接指针的方式访问。

二、JVM虚拟机执行子系统

2.1 类文件结构

2.2 虚拟机类加载机制

2.2.1 类加载的时机

2.2.2 连接(Linking)

2.2.3 初始化

2.2.3.1 有且只有四种情况必须立即对类进行“初始化”

1)new、getstatic、putstatic、invokestatic

2)java.lang.relect包

3)初始化一个类,如果父类没有初始化,先初始化父类

4)虚拟机启动时,初始化主类(包含main方法()的那个类)

2.3 类加载的过程

加载      ===>验证===>准备===>解析   ===>初始化===>使用===>卸载 

2.3.1 加载

1)通过类的全限定名来获取定义此类的二进制字节流

(1)从zip包中读取,典型场景:成为jar、ear、war格式的基础。

(2)从网络中获取,典型场景:Applet。

(3)运行时计算生成,典型场景:动态代理技术。

(4)由其他文件生成,典型场景: JSP应用。

(5)从数据库总读取,场景相对较少。

2)将这个字节流所代表的静态存储结果转化为方法区的运行时数据结构;

3)在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口

2.3.2 验证

验证是虚拟机对自身保护的一项重要工作。

1)文件格式验证
2)元数据验证
3)字节码验证
4)符号引用验证

2.3.3 准备

2.3.4 解析

2.3.5 初始化

2.4 类加载器

2.4.1 类与类加载器

对于任意一个类,都需要由它加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性。

比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提之下才有意义。

2.4.2 双亲委派模型

2.5 类加载及执行子系统的案例与实战

 

三、JVM程序编译及代码优化

四、JVM高效并发

五、String

5. 1 String类为什么要设计成final

http://blog.csdn.net/fenglibing/article/details/5486449

将方法或类声明为final主要目的是:确保它们不会再子类中改变语义。String类是final类,这意味着不允许任何人定义String的子类。换言之,如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。
——《Java核心技术 卷I》

5.2 StringBuffer和StringBuilder的区别

http://blog.csdn.net/mad1989/article/details/26389541

六、Java集合框架

6.1 HashMap

http://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE%9E%E7%8E%B0/

http://tracylihui.github.io/categories/Java%E9%9B%86%E5%90%88/

6.2 ConcurrentHashMap

锁分段技术

http://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/

http://www.infoq.com/cn/articles/ConcurrentHashMap

6.3 Java容器的线程安全 

http://blog.csdn.net/zhangchaoyangsun/article/details/8664526

http://blog.csdn.net/jiyiqinlovexx/article/details/51030720

http://www.cnblogs.com/shijiaqi1066/p/3412275.html

七、内存映射原理

http://www.cnblogs.com/huxiao-tee/p/4660352.html

十、数据库

10.1 SQL的读法

官方的正确的执行顺序如下:

  (8)SELECT  
  (9) DISTINCT 
  (11) <TOP_specification> <select_list> 
  (1)  FROM <left_table>  
  (3) <join_type> JOIN <right_table> 
  (2) ON <join_condition> 
  (4) WHERE <where_condition> 
  (5) GROUP BY <group_by_list> 
  (6) WITH {CUBE | ROLLUP} 
  (7) HAVING <having_condition> 
  (10) ORDER BY <order_by_list>

举例:

1、 select username,count(1) 
2from gv$session t
3where wait_class <> ‘Idle’
4group by username 
5having count(1) >=2 
6order by 2 desc

读作:

1from gv$session t
2where wait_class <> ‘Idle’
3group by username 
4having count(1) >=2 
5、 select username,count(1) 
6order by 2 desc

10.2 Oracle优化

RBO和CBO的基本概念

10.3 Oracle中的rownum

10.4 Oracle分页

实现oracle分页常用三种方法:rowid、分析函数、rownum

oracle分页的问题

Oracle 分页查询 为什么需要嵌套