-
在浏览器输入URL,按下回车之后的流程?
DNS域名解析,得到IP地址
解析出IP地址后,根据IP地址和默认端口80和服务器建立连接
浏览器发出读取文件(URL中域名后边部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器
服务器对浏览器的请求作出响应,并把对应的html文本发送给浏览器
释放TCP连接(四次挥手断开连接)
浏览器解析该HTML文本并显示内容
-
说一下Java的内存模型
Java内存模型(JMM)规定了所有的变量都存储在主内存中(类比操作系统的主内存)。每条线程还有自己的工作内存(类比前面讲的处理器高速缓存),线程的工作内存中保存了主内存的变量副本,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的数据
JMM最重要的3点内容分别是重排序、内存可见性、原子性。
-
Java的内存结构
-
什么是栈帧
每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame).每个独立的栈帧一般包括:
- 函数的返回地址和参数
- 临时变量: 包括函数的非静态局部变量以及编译器自动生成的其他临时变量
- 函数调用的上下文
-
什么是索引
索引可以大大提高MySQL的检索速度
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。建立索引会占用磁盘空间的索引文件
-
Innodb对比其他数据库引擎的优势是什么
InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎
nnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的
InnoDB支持外键完整性约束
InnoDB被用在众多需要高性能的大型数据库站点上
主键尽可能小.包括索引
尽量避免全表扫描.因为会造成表锁
尽量缓存所有的数据和索引,提高响应速度, -
myisam引擎
1.mysql默认引擎,不支持事务*
2.表级锁定,更新时,锁定机制是整张表被锁定,其它连接无法更新表的数据,效率比较低下.锁的机制成本很少,但大大降低了并发性能*
3.读写互相阻塞,写的时候阻塞读,读的时候也阻塞写,但读与读之间不阻塞*
4.只对索引进行缓存,虽然key_buffer可以大幅提高性能,减少磁盘IO,但对数据不缓存
5.适合读业务比较多的生产环境,比如BLOG等,读的速度比较快.
6.占用资源比较少.服务器硬件不好时.可以考虑使用
7.数据恢复没有innodb引擎恢复的完美
8.支持全文索引,不支持外键约束1.尽量索引,缓存机制
调整读写优先级
启用延迟插入.
生产环境应用memcache缓存的多.Mysql本身的缓存为用少 -
了解JVM吗?说一下.class文件加载过程。
(1) Loading:把class采用双亲委派机制load到内存中,也就是把class文件中的字节装载到内存上。
(2) Linking:
Linking过程中又分为以下三步:
a. Verification:检验文件类型,class的魔数是CAFEBABE,如果是其他的格式就会被剔除掉, 不进入下一阶段。
b. Preparation:为静态变量赋默认值。
c. Resolution:将类、方法、属性等符号引用解析为直接引用;将class文件中常量池中的符号 引用解析为指针、偏移量等内存地址的直接引用。
(3) Initializing:静态变量赋初始值,也是在这个阶段调用静态代码块。
-
说一下Java堆,新生代是怎么转化为老年代的?
Java堆 = 老年代 + 新生代
新生代 = Eden + S0 + S1
当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区。
大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年态;
如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。
老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存堆 – 包括年轻代和年老代。
Major GC 发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。
-
什么情况下会发生栈内存溢出
栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果。
如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是无法申请到足够的内存去完成扩展,或者在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一个OutOfMemory 异常。(线程启动过多)
-
垃圾收集器
CMS(Concurrent Mark Sweep) 收集器: 是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重新标记,并发清除,收集结束会产生大量空间碎片。
G1收集器: 标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。不会产生空间碎片,可以精确地控制停顿。
-
怎么判断一个Object需要回收
- 引用计数算法
- 可达性分析算法(Java使用的这一种)
引用计数算法是在对象中加入一个计数器,当对象被引用,计数器+1,当引用失效,计数器-1这种算法实现简单,效率高,但是有一个严重的问题会导致内存泄漏,那就是对象之间循环引用,比如说A对象持有B对象的引用,B对象持有A对象的引用,那么A和B的计数器值永远>=1,也就是说这两个对象永远不会被回收
可达性分析算法,Java中定义了一些起始点,称为GC Root,当有对象引用它的时候,就把对象挂载在它下面,形成一个树状结构,当一个对象处于一个这样的树里时,就认为此对象是可达的,反之是不可达,
如图 Object1,Object2,Object3是对象可达的,Object4,Object5,Object6是不可达的
那么有哪些可以作为GC Root呢?
静态属性(被static修饰的属性)
常量(被static final修饰的属性)
虚拟机栈(本地变量表)中引用的对象
本地方法栈中引用的对象 -
多线程,怎么解决死锁?
所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
解决:
- 加锁顺序(线程按照一定的顺序加锁)
- 加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
- 死锁检测
-
进程间的通信方式
管道( pipe ):
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
有名管道 (namedpipe) :
有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
信号量(semophore ) :
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
消息队列( messagequeue ) :
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号 (sinal ) :
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存(shared memory ) :
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
套接字(socket ) :
套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同设备及其间的进程通信。 -
线程间的通信方式
锁机制:包括互斥锁、条件变量、读写锁
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。 -
HTML常用标签
<div>、<a>、<img>、<h1>-<h6>、<p>、<table>、<form>、<ul>、<ol>、<dl>