Java 基础

2018-03-13  本文已影响0人  CHSmile

1.java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码;传统的Java程序经过编译,生成Java字节码保存在class文件中,java虚拟机通过解码class文件中的内容来运行程序。而Dalvik虚拟机运行的是Dalvik字节码,所有的Dalvik字节码由Java字节码转换而来,并被打包到一个DEX(Dalvik Executable)可执行文件中Dalvik虚拟机通过解释Dex文件来执行这些字节码。

2.Dalvik可执行文件体积更小。SDK中有一个叫dx的工具负责将java字节码转换为Dalvik字节码。

3.java虚拟机与Dalvik虚拟机架构不同。java虚拟机基于栈架构。程序在运行时虚拟机需要频繁的从栈上读取或写入数据。这过程需要更多的指令分派与内存访问次数,会耗费不少CPU时间,对于像手机设备资源有限的设备来说,这是相当大的一笔开销。Dalvik虚拟机基于寄存器架构,数据的访问通过寄存器间直接传递,这样的访问方式比基于栈方式快的多.

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

类的加载过程包括加载,验证,准备,解析,初始化五个阶段,这里的几个阶段是按顺序开始的,而不是按顺序进行或者完成,因为这些阶段通常交叉进行的。

image.png
五个加载过程详解

双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
双亲委派机制:
1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。


image.png

双亲委派模型意义:
系统类防止内存中出现多份同样的字节码
保证Java程序安全稳定运行

虚拟机栈 VM Stack
本地方法栈 Native Method Stack
堆 Heap
方法区 Method Area
程序计数器

image.png
内存模型详情

Heap(堆) Method Area(方法区)

新生代垃圾收集机制

新生代又可分为三个部分:

在三个区域中有两个是Survivor区。对象在三个区域中的存活过程如下:

  1. 大多数新生对象都被分配在Eden区。
  2. 第一次GC过后Eden中还存活的对象被移到其中一个Survivor区。
  3. 再次GC过程中,Eden中还存活的对象会被移到之前已移入对象的Survivor区。
  4. 一旦该Survivor区域无空间可用时,还存活的对象会从当前Survivor区移到另一个空的Survivor区。而当前Survivor区就会再次置为空状态。
  5. 经过数次在两个Survivor区域移动后还存活的对象最后会被移动到老年代。

如上所述,两个Survivor区域在任何时候必定有一个保持空白。如果同时有数据存在于两个Survivor区或者两个区域的的使用量都是0,则意味着你的系统可能出现了运行错误。

在新生代中,使用“停止-复制”算法进行清理,将新生代内存分为2部分,1部分 Eden区较大,1部分Survivor比较小,并被划分为两个等量的部分。每次进行清理时,将Eden区和一个Survivor中仍然存活的对象拷贝到 另一个Survivor中,然后清理掉Eden和刚才的Survivor。

老年代垃圾收集机制

老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续。

  • 新生代:大部分的新创建对象分配在新生代。因为大部分对象很快就会变得不可达,所以它们被分配在新生代,然后消失不再。当对象从新生代移除时,我们称之为"minor GC"。
  • 老年代:存活在新生代中但未变为不可达的对象会被复制到老年代。一般来说老年代的内存空间比新生代大,所以在老年代GC发生的频率较新生代低一些。当对象从老年代被移除时,我们称之为"major GC"(或者full GC)。

垃圾回收详解

标记清除,标记整理,复制,分代收集

适配器模式:将原有类接口转换为目标代码需求的接口。
装饰者模式:能动态的新增或组合对象的行为
外观模式:注重多个类的集成、统一适配

垃圾回收机制:用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。
调用System.gc():System.gc() 的作用只是提醒虚拟机进行垃圾回收,回不回收得由虚拟机决定。

GC调优的目标分为以下两类:

  • 降低移动到老年代的对象数量
  • 缩短Full GC的执行时间

四大引用
强,软,弱,虚,并说明下合适GC
垃圾搜集算法有哪些?G1算法?

LruCache是个泛型类,主要算法原理是把最近使用的对象用强引用(即我们平常使用的对象引用方式)存储在LinkedHashMap中,通过内部一个双向的循环链表实现的。当缓存满时,把最近最少使用的对象从内存中移除,并提供了get和put方法来完成缓存的获取和添加操作。
Android LruCache源码分析

静态属性和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏.
非静态方法可以被继承和重写,因此可以实现多态。

UDP:
将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小在限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP:
建立连接,形成传输数据的通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低

Socket: Socket不属于协议范畴,而是一个调用接口(API),Socket是应用层与TCP/IP协议族通信的中间软件抽象层。它既可使用下层的 TCP,也可以使用UDP,Socket连接是长连接,理论上客户端和服务器端一旦建立连接将不会主动断开此连接。
Http: 超文本传输协议,首先它是一个协议,并且是基于TCP/IP协议基础之上的应用层协议。HTTP是基于请求-响应形式并且是短连接,并且是无状态的协议。
长连接:建立一个连接后保持一段时间,这段时间多个请求和响应使用这个连接。
短连接:每一次请求建立一个连接,等服务器响应返回就关闭连接。

image.png
  1. 三次握手

(1) 客户端向服务器端发送连接请求包SYN(syn=j),等待服务器回应;
(2) 服务器端收到客户端连接请求包SYN(syn=j)后,将客户端的请求包SYN(syn=j)放入到自己的未连接队列,此时服务器需要发送两个包给客户端;

(3) 客户端收到服务器的ACK(ack=j+1)和SYN(syn=k)包后,知道了服务器同意建立连接,此时需要发送连接已建立的消息给服务器;向服务器发送连接建立的确认包ACK(ack=k+1),回应服务器的SYN(syn=k)告诉服务器,我们之间已经建立了连接,可以进行数据通信。

  1. 为什么不能只两次握手?
    有了三次握手的详细步骤,就可以分析为什么需要三次握手而不是两次握手了。

    三次握手的目的:消除旧有连接请求的SYN消息对新连接的干扰,同步连接双方的序列号和确认号并交换TCP 窗口大小信息

设想:如果只有两次握手,那么第二次握手后服务器只向客户端发送ACK包,此时客户端与服务器端建立连接。在这种握手规则下:
假设:如果发送网络阻塞,由于TCP/IP协议定时重传机制,B向A发送了两次SYN请求,分别是x1和x2,且因为阻塞原因,导致x1连接请求和x2连接请求的TCP窗口大小和数据报文长度不一致,如果最终x1达到A,x2丢失,此时A同B建立了x1的连接,这个时候,因为AB已经连接,B无法知道是请求x1还是请求x2同B连接,如果B默认是最近的请求x2同A建立了连接,此时B开始向A发送数据,数据报文长度为x2定义的长度,窗口大小为x2定义的大小,而A建立的连接是x1,其数据包长度大小为x1,TCP窗口大小为x1定义,这就会导致A处理数据时出错。很显然,如果A接收到B的请求后,A向B发送SYN请求y3(y3的窗口大小和数据报长度等信息为x1所定义),确认了连接建立的窗口大小和数据报长度为x1所定义,A再次确认回答建立x1连接,然后开始相互传送数据,那么就不会导致数据处理出错了。

  1. tcp攻击,如何进行攻击
    TCP连接攻击
    TCP攻击方式

Java设计模式

1、String类时final类,所以是不可继承的;
2、String类是的本质是字符数组char[];
3、Java运行时会维护一个String Pool(String池),JavaDoc翻译很模糊“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。

抽象类:
1.抽象类不能创建对象,因为其中包含了未实现的抽象方法
2.继承抽象类的子类,如果没有实现抽象方法,则这个类也是抽象类
3.如果使用抽象类,必须使用子类来实现并覆写抽象类中所有抽象方法
4.abstract类中可以有abstract方法,也可以有非abstract方法

接口
1.接口体的声明包含`常量的声明(没有变量)和抽象方法.接口体中只有抽象方法,没有普通的方法,而且接口体中所有的常量的访问权限一定是public,而且是static常量,所有的抽象方法的访问权限一定都是public
2.接口可以实现多继承
3.接口主要用于被实现,接口中的所有方法,在子类中必须全部实现

Java中静态属性和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏。

原因:

  1. 静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成,不需要继承机制及可以调用。如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为"隐藏"。如果你想要调用父类的静态方法和属性,直接通过父类名.方法或变量名完成,至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在"隐藏"的这种情况。
  2. 多态之所以能够实现依赖于继承、接口和重写、重载(继承和重写最为关键)。有了继承和重写就可以实现父类的引用指向不同子类的对象。重写的功能是:"重写"后子类的优先级要高于父类的优先级,但是“隐藏”是没有这个优先级之分的。
  3. 静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。非静态方法可以被继承和重写,因此可以实现多态。

所有的类直接或者间接的继承了Object类

方法:

String toString()
boolean equals(Object obj)
int hashCode();//返回对象的哈希码值,标示对象的唯一性

源码解读
Java根类Object的方法说明

String类是不可变类,任何对String的改变都会引发新的String对象的生成;StringBuffer是可变类,任何对它所指代的字符串的改变都不会产生新的对象,支持并发操作,线性安全的,适合多线程中使用
StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用

String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
String,StringBuffer与StringBuilder的区别

静态内部类、局部内部类、匿名内部类、成员内部类
1.内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法
2.内部类的类体中不可以声明类变量和类方法,外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员
3.内部类仅供它的外嵌类使用,其他类不可以用某个类的内部类声明对象。
4.局部内部类中,如果要访问局部变量时,则局部变量需要final修饰

image.png

List:存储对象是有序的,可以重复的
ArrayList:使用的数据结构是数组,线程不安全,查找速度快,增删速度慢
LinkedList:使用的数据结构是链表,线程不安全,查找速度慢,增删速度快
Vector:使用的数据结构是数组,线程安全,查找速度快,增删速度慢,被ArrayList替代

Set:存储对象是无序的,不可以重复的

HashSet:底层使用的数据结构是哈希表,线程不安全
保证对象唯一的原理:
先判断hashCode()值,如果都不同就直接加入集合,如果哈希值相同了
在调用equals()方法,如果equals()方法返回值为true,则认为集合中存在该对象,不加入集合

TreeSet:底层使用的数据结构是二叉树,线程不安全
保证集合中对象唯一的方式:依据compareTo()或compare()的返回值是否为0
会对存入集合的对象进行排序

排序方式一:让存入集合中的对象具备可比较性
让存入集合中的对象所属的类实现Comparable<T>接口中的
int compareTo(T t) 方法

排序方式二:让集合具备排序功能
定义一个比较器,实现Comparator<T>接口中的 int compare(T t1,T t2)方法
把比较器对象作为参数传递给TreeSet<E>集合的构造方法
当集合中的对象具备可比较性,且存在比较器时,比较器优先被使用

Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性

|--Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的。jdk1.0效率低
|--HashMap:底层是哈希数据结构,允许使用null键null值,该集合时不同步的.jdk1.2 效率高
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序

HashSet 和 HashMap 的比较

ArrayList:使用的数据结构是数组,线程不安全,查找速度快,增删速度慢
LinkedList:使用的数据结构是链表,线程不安全,查找速度慢,增删速度快

ConCurrentHashMap实现

  1. hashmap如何put数据(从hashmap源码角度讲解)?
  2. 为什么用TreeMap不用HashMap
  3. HashSet与HashMap怎么判断集合元素重复
    HashMap实现

SpareArray原理

TreeMap实现

  1. 强引用置为null,会不会被回收?
    Java四种引用

sqlite升级,增加字段的语句

进程:是一个正在执行中的程序
每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:就是进程中的一个独立的控制单元
线程在控制着进程的执行
一个进程中至少有一个线程
Java VM 启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行
而且这个线程运行的代码存在于main方法中
该线程称之为主线程
扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程

线程与进程

  1. 定义类继承Thread类,复写Thread类中的run方法,调用线程的start()方法
  2. 实现Runnable接口
  3. 接口式的匿名内部类new Thread().start()

进程调度

Java通过Executors提供四种线程池,分别为:

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

线程池介绍

线程安全问题:多个线程共享数据时,可以出现数据不一致性问题

解决线程安全问题的方式: 加锁
  锁(对象锁):Java对象中存一个标志("互斥锁"),保证对象在同一时刻,只能有一个线程去使用(访问)它 ,一个线程访问加锁的对象,其它线程只能等这个线程释放锁后 ,才能访问。 
注: 加锁操作后,由于其它线程不停地判断锁是否释放(解锁),所以会影响执行效率
  
加锁的方式有三种:(synchronized)
1、  同步非静态方法: 在方法声明时,增加synchronized修饰符,针对this对象加锁,如果一个线程访问了这个方法,其它线程在访问this对象的同步方法时,
会进入等待状态,直到这方法执行完成后,才能访问。
2、  同步静态方法:在静态方法声明时,增加synchronized修饰,针对.Class对象加锁, 如果一个线程访问了这个方法,其它线程在访问这个类的同步静态方法时,会进入等待状态,直到这方法执行完成后,才能访问静态函数对应的锁对象是:字节码文件对象   Class   锁的表示:   类名.class                   
3、  同步代码块:存在同步代码区域,这个区域主要是共享数据的操作(多条语句)
格式:  synchronized(对象){ 共享数据的操作语句; }  其中对象是任意的
注:同步函数与同步代码块锁对象不是同一个
Lock接口:
    lock()获取锁
    unlock()释放锁
    ReentrantLock类:接口Lock的实现类

一个线程拿到A资源对象锁后,还想要等着拿到B资源的对象锁,
另一线程拿到B资源对象锁后,还想要等着拿到A资源的对象锁

产生死锁的四个必要条件:

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
死锁避免与预防


并发集合详解

synchronized与Lock的区别

CAS介绍

volatile用法

对象的生命周期

1.新建状态(New):新创建了一个线程对象。
2.就绪状态(Runnable)(可运行):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

进程状态详解

进程保活

WebSocket相关以及与socket的区别

ReentrantLock 、synchronized

多线程断点续传原理

手写生产者/消费者模式
NIO

volatile synchronize lock 的原理

如何自己实现线程池。线程池内的队列如何管理。线程池大小N的话,连续push进来M个的任务(M>>N),如何处理,比如20大小的线程池扔进来10000个任务
写一个死锁,死锁是怎样产生的,怎样防止死锁
bitmap recycler 相关

算法判断单链表成环与否?

常用数据结构简介
判断环(猜测应该是链表环)
排序,堆排序实现
链表反转

如何保证多线程读写文件的安全?
多线程的方式有哪些?

  1. new Thread()
  2. AsyncTask
  3. Handler
  4. IntentService
  5. ThreadPoolExecutor

数据库数据迁移问题
设计模式相关(例如Android中哪里使用了观察者模式,单例模式相关)
x个苹果,一天只能吃一个、两个、或者三个,问多少天可以吃完
java注解

内部类和静态内部类和匿名内部类,以及项目中的应用
ReentrantLock的内部实现

一个无序,不重复数组,输出N个元素,使得N个元素的和相加为M,给出时间复杂度、空间复杂度。手写算法

Http2.0与1.1有啥区别(由这里开始就炸了,完全没复习计算机网络,尤其还是偏背诵的知识的) 5. 有哪些二进制传输协议

差值器&估值器

性能优化如何分析systrace?
string to integer

堆排序过程,时间复杂度,空间复杂度
快速排序的时间复杂度,空间复杂度
手写算法题。一共有3个,面试官随机选择一个。猫扑素数;1到n,求1的个数;单词反转

Http和Https的区别?
1)Https是ssl加密传输,Http是明文传输
2)Https是使用端口443,而Http使用80
3)HttpsSSL+HTTP协议构建的可进行加密传输、身份认证的网络协议要比Http协议安全
4)Https协议需要到CA申请证书

加密算法有哪些?对称加密和非对称加密的区别?
MD5,SHA1,Base64,RSA,AES,DES

对称:使用相同密钥,需要在网络传输,安全性不高。
非对称:使用一对密钥,公钥和私钥,私钥不在网络传输,因此安全性高。

二叉树,给出根节点和目标节点,找出从根节点到目标节点的路径
数据结构中堆的概念,堆排序
排序,快速排序的实现
树:B+树的介绍
二叉树 深度遍历与广度遍历
B树、B+树
图:有向无环图的解释
多叉树的后续遍历

网络五层结构

数据结构,搜索二叉树的一些特性,平衡二叉树。
hashmap是如何解决hash冲突的
进程与线程区别
写了一个二分查找和单例模式
http中的同步和异步

java比较重要的几个特性
字符串反转,讨论复杂度

给定一个int型 n,输出1~n的字符串例如 n = 4 输出“1 2 3 4”
输出所有的笛卡尔积组合
单例模式
最长上升子序列

常见编码方式;utf-8编码中的中文占几个字节;int型几个字节

实现一个Json解析器(可以通过正则提高速度)

MVC MVP MVVM; 常见的设计模式;写出观察者模式的代码

TCP的3次握手和四次挥手;TCP与UDP的区别

HTTP协议;HTTP1.0与2.0的区别;HTTP报文结构

HTTP与HTTPS的区别以及如何实现安全性

Java基础
集合类以及集合框架;HashMap与HashTable实现原理,线程安全性,hash冲突及处理算法;ConcurrentHashMap

数据一致性如何保证;Synchronized关键字,类锁,方法锁,重入锁

同步的方法;多进程开发以及多进程应用场景

服务器只提供数据接收接口,在多线程或多进程条件下,如何保证数据的有序到达

ThreadLocal原理,实现及如何保证Local属性

String StringBuilder StringBuffer对比

接口与回调;回调的原理;写一个回调demo;

泛型原理,举例说明;解析与分派
修改对象A的equals方法的签名,那么使用HashMap存放这个对象实例的时候,会调用哪个equals方法

堆和栈在内存中的区别是什么(数据结构方面以及实际实现方面)

最快的排序算法是哪个?给阿里2万多名员工按年龄排序应该选择哪个算法?堆和树的区别;写出快排代码;链表逆序代码

求1000以内的水仙花数以及40亿以内的水仙花数

子串包含问题(KMP 算法)写代码实现

万亿级别的两个URL文件A和B,如何求出A和B的差集C,(Bit映射->hash分组->多文件读写效率->磁盘寻址以及应用层面对寻址的优化)

蚁群算法与蒙特卡洛算法

写出你所知道的排序算法及时空复杂度,稳定性

百度POI中如何试下查找最近的商家功能(坐标镜像+R树)

前台切换到后台,然后再回到前台,Activity生命周期回调方法。
弹出Dialog,生命值周期回调方法。

多进程场景遇见过么?
关于handler,在任何地方new handler 都是什么线程下

上一篇 下一篇

猜你喜欢

热点阅读