Java进阶
一只老风铃
欣于所遇,暂得于己,快然自足。
展开
-
Java 重载与重写
链接:https://www.nowcoder.com/questionTerminal/7b2152a85b9a4ebab6dfda7e995a8491?orderByHotValue=1&mutiTagIds=570&page=1&onlyReference=false来源:牛客网方法重写的原则:重写方法的方法名称、参数列表必须与原方法的相同,返回类型可以相同也可以是原类型的子类型(从Java SE5开始支持)。 重写方法不能比原方法访问性差(即访问权限不允许缩小.原创 2020-07-29 15:11:02 · 171 阅读 · 0 评论 -
Java 快速失败和安全失败
一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的结构进行了修改(增加、删除),则会抛出Concurrent Modification Exception。原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果结构发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expec...原创 2020-07-28 14:05:58 · 287 阅读 · 0 评论 -
深入JVM Web容器-经典类加载器架构
在Class文件格式与执行引擎部分,用户的程序能直接影响的内容并不多,Class文件的格式,类加载时机,如何连接,以及具体的字节码指令执行都由虚拟机控制,用户程序无法控制。能进行控制的,主要是字节码的生成和类加载器部分主流的Java Web容器 如Tomcat Weblogic WebSphere都实现了自定义的类加载器,而一个功能健全的Web服务器,都要解决主要的以下几个问题——部署在同...原创 2019-03-02 14:49:58 · 352 阅读 · 0 评论 -
深入JVM 双亲委派模型
从虚拟机角度看,只存在2种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身一部分; 一种是所有其他的类加载器,使用Java语言实现,独立于虚拟机,继承于java.lang.ClassLoader从Java开发人员的角度来看,类加载器可进一步划分,一般情况下提供3种系统的类加载器——启动类加载器(Bootstr...原创 2019-02-26 15:24:24 · 3639 阅读 · 0 评论 -
深入JVM 方法区和常量池溢出
Java虚拟机运行数据区中,常量池属于方法区内部,主要存放类加载的元信息、常量、静态变量、即时编译的代码,还有编译后生成的字面值 符号引用等而最经典的String.intern()方法是一个native本地方法,它的作用:如果字符串常量池中已经等于此String的对象字符串,则返回常量池中的这个String对象;否则,将此String对象放入常量池,并返回String对象的引用案例演示: ...原创 2019-02-20 23:27:42 · 1343 阅读 · 0 评论 -
深入JVM 虚拟机栈和本地方法栈溢出
由于在HotSpot虚拟机中不区分虚拟机栈和本地方法栈,因此,对于HotSpot而言,-Xoss设置本地方法栈的参数失效,栈的容量大小只有Xss参数设置。虚拟机栈主要出现2种错误异常如果线程请求的栈深度大于虚拟机栈所允许的最大深度,抛出StackOverFlowError错误异常 如果虚拟机栈在拓展栈时无法申请到足够的内存空间,抛出OutOfMemoryError错误异常实验限制于单线...原创 2019-02-20 22:54:33 · 1067 阅读 · 0 评论 -
深入JVM 实战堆内存溢出
在Java运行时数据区域中,除程序计数器外,其它几个运行时区域都有可能发生OutOfMemoryError错误异常 ——虚拟机启动可以设定虚拟机启动参数,以Eclipse IDE为例,虚拟机启动参数 VM Args 将影响虚拟机内存空间 1 Java堆溢出 在主线程中不断创建对象,设置虚拟机启动参数VM Args: -Xms20m -Xmx 20m -XX:+HeadDu...原创 2019-02-20 22:17:50 · 222 阅读 · 0 评论 -
深入JVM 类加载器
类加载阶段的通过一个类的全限定名获取该类的二进制字节流这个动作可以人为的放到虚拟机外部实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为 类加载器类加载器是Java语言的创新特性,也是其流行的原因,类加载器在类层次划分,热部署,代码加密等领域大放异彩,成为Java技术体系的一个重要组成部分类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用远不止类加...原创 2019-02-26 14:23:12 · 191 阅读 · 0 评论 -
深入JVM 对象的内存布局与访问定位
在经典Java 虚拟机HotSpot中,对象在堆中的布局分为3块:对象头(object header)、 实例数据(Instance Data)、 对齐填充 HotSpot虚拟机的对象头包括两部分第一部分是用于存储对象自身的运行时数据,如哈希码(hashcode)、GC分代年龄、锁相关信息,这部分数据长度在32位和64位中分别是32bit 64bit 称为 Mark Word 。...原创 2019-02-20 21:44:14 · 258 阅读 · 0 评论 -
深入JVM 对象的创建
——Java作为纯面向对象的语言,运行过程无时无刻都有对象被创建。在语言层面上,创建对象(克隆、反序列化)通常仅仅体现为new关键字,而虚拟机中实际创建过程则更为复杂。 虚拟机遇到一条new指令后,首先检查这个指令的参数是否能在常量池种定位到这个类的符号引用,并且检查这个符号引用代表的类是否被类加载、解析、和初始化,否则,必须先进行相应的类加载过程。 类加载检查完后,紧接...原创 2019-02-20 20:49:53 · 117 阅读 · 0 评论 -
深入JVM 运行时数据区域
——Java虚拟机在执行Java程序时将其所管理的内存划分为若干区域,各个区域都有各自的用途,以及创建和销毁的时间,有的区域随虚拟机进程的启动存在,有的依赖于用户线程的启动和结束而建立和销毁——Java虚拟机所管理的内存包含以下几个运行时数据区域——程序计数器pc程序计数器是一块占用空间较小的区域,是当前线程执行的字节码的指示器。在虚拟机的概念模型中,字节码解释器工...原创 2019-02-20 20:13:52 · 143 阅读 · 0 评论 -
深入JVM 运行时栈帧结构
栈帧(stack Frame)是用于支持虚拟机进行方法调用和执行的数据结构,它是虚拟机运行时数据区中虚拟机栈的栈元素。栈帧存储方法的局部变量表,操作数栈,动态连接,方法返回地址等信息。每一个方法的执行过程,都对应着一个栈帧入栈和出栈的过程每一个栈帧需要的各部分数据结构,在编译程序代码时,都已确定并写入方法表的Code属性中,因此一个栈帧需要分配多大的内存,不会受到程序运行期间变量数据的影响,而...原创 2019-02-26 15:44:12 · 269 阅读 · 0 评论 -
深入JVM invokedynamic指令
某种程度上讲 invokedynamic指令和MethodHandle机制的作用是一样的,都是为了解决分派机制固化在虚拟机的特点,让用户有更高的自由度是其设计的目的。MethodHandle类似,只不过methodHandle采用Java语言和API进行实现,invokedynamic则是字节码来完成。每一个含有invokedynamic指令的位置称为动态调用点dynamic Call sit...原创 2019-03-02 13:24:50 · 523 阅读 · 0 评论 -
深入JVM 解析执行
通常而言,虚拟机的执行引擎在执行Java代码的时候都有解释执行(通过解释器执行)和编译执行(通过即使编译器直接翻译成本地机器码)2种选择。——解释执行在老版本的虚拟机中,通常认为Java语言是解释执行的语言,但现代主流虚拟机都包含即使编译器,Class文件到底是被解释执行还是编译执行,并不确定,不论是解释还是编译,也不论环境是实际物理机还是虚拟机,对于应用程序,机器都需要进行一定步骤。...原创 2019-03-02 13:54:04 · 242 阅读 · 0 评论 -
深入JVM Java内存模型
Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致性的内存访问效果。而相对而言,C C++是直接使用物理硬件和操作系统的内存模型,因此在不同的平台上存在差异,可能导致程序在不同平台执行效果不同,存在耦合的弊端定义Java内存模型需要考虑得当,必须足够严谨,才能让Java的并发内存访问不出错,但是,也必须足够宽松,使...原创 2019-03-13 17:47:19 · 289 阅读 · 0 评论 -
深入JVM 硬件的效率与一致性
让计算机并发执行若干个运算任务与更充分利用计算机的效能之间的因果关系,看似顺理成章,实际它们之间关系远远没有想象的简单,其中一个重要的复杂性来源于绝大多数的运算任务不可能单靠 处理器计算完成,那么处理器与内存的交互,如读取运算数据,存储运算结果,类似的IO操作是很难消除的(无法仅仅依靠寄存器完成所有计算任务)由于计算机的存储设备与处理器之间的速度代沟,所以现代计算机系统不得不加入一层读写速度尽...原创 2019-03-13 17:29:21 · 286 阅读 · 0 评论 -
深入JVM 原子性、可见性、有序性
Java内存模型围绕着并发过程中如何处理原子性、可见性和有序性三个特征来建立的——原子性由Java内存模型来直接保证原子性操作包括Read Load Assign Use Store Write可以认为基本数据类型的读写访问具备原子性,如果应用场景需要一个更大范围的原子性保证,Java内存模型提供Lock Unlock操作来提供支持,尽管虚拟机未把Lock Unlock操作直接开放接口使用...原创 2019-03-16 13:52:27 · 587 阅读 · 0 评论 -
深入JVM 内存间交互操作
Javan内存模型定义了8种操作来完成主内存与工作内存的读写交互,虚拟机实现保证每一种操作都是原子的,不可再分的Lock锁定 作用于主内存变量,将变量标志为一条线程所独占 Unlock解锁 作用于主内存变量,将处于锁定的变量释放出来 Read读取 作用于主内存变量,它将一个变量的值从主内存传输到线程的工作内存中 Load载入 作用于工作内存变量,它把从主内存...原创 2019-03-14 10:33:13 · 785 阅读 · 0 评论 -
深入JVM 语法糖-泛型
语法糖是程序语言提供给程序设计人员的用于提高开发效率,降低错误的设计。可以看作是编译器实现的小把戏,这些小把戏背后可能会使的效率提升,其中Java语言中最著名的是泛型泛型是JDK1.5的一项新增特性,它的本质的参数化类型的应用,也就是说所操作类型被指定为一个参数。这种参数类型可以用在类,接口和方法的创建中,分别是泛型类,泛型接口,泛型方法泛型思想早在C++语言的模板中就开始出现,在早版本的...原创 2019-03-09 10:20:21 · 262 阅读 · 0 评论 -
深入JVM 动态代理
对于Spring而言,如果Bean是面向接口编程,那么在Spring内部都是通过动态代理的方式对Bean进行增强的。动态代理中所谓的动态,是针对使用Java代码实际编写了代理类的静态代理而言的,它的优势不在于省去了编写代理类的工作量,而是实现了可以在原始类和接口还未知的时候,就确定代理类的行为,当代理类与原始类脱离直接联系后,就可以重用于不同的应用场景中。实例演示:public clas...原创 2019-03-03 16:36:36 · 1097 阅读 · 0 评论 -
深入JVM 栈帧数据结构
——局部变量表局部变量表(Local Variadble Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。在Java程序编译为Class文件时,在方法的Code属性的max_locals数据项中确定该方法所需要分配的局部变量表的最大容量局部变量表的容量以变量槽(slot)为最小单位,虚拟机规范中没有规定槽的大小,它允许具体数据类型随着处理器、操作系统而大小发生改变...原创 2019-02-26 16:26:29 · 720 阅读 · 0 评论 -
深入JVM OSGI-灵活的类加载架构
OSGI(Open Service Gateway Initiative)是一个由OSGI联盟联合制定的一个基于Java语言的动态模块化规范,而后这个规范得到不断发展,并具备成熟的特性,最著名的应用案例就是: Eclipse IDE 另外许多大型软件平台和服务器都是基于OSGI规范来实现的。OSGI中的每个模块(Bundle)与普通的Java类库区别不大,2者都是由JAP格式封装,并且内部存储...原创 2019-03-02 15:15:04 · 692 阅读 · 0 评论 -
深入JVM MethodHandle
——动态语言类型动态类型语言的关键特征是它的类型检查主体过程发生在运行期而不是编译期,如: python javascript PHP等,相对的,编译期需要进行类型检查的语言有C++ Java——obj.println("test");对于这段代码,静态类型语言如Java编译期就会检查obj是否是printStream类型范围,而对于javascript语言则不会检查,它直到运行期间才...原创 2019-03-01 20:49:09 · 472 阅读 · 0 评论 -
深入JVM 动态分派
动态分派与多态性的另一个重要体现: 重写(Override) 有着十分密切的关系。一个动态分派的例子:public class DynamicDispatch { static abstract class Human { protected abstract void say(); } static class Man extends Human { @Overr...原创 2019-03-01 20:10:54 · 247 阅读 · 0 评论 -
深入JVM 静态分派
分派调用的过程揭示了面向对象语言的多态性特征,其中重载和重写是其重要组成部分一个静态分派例子:public class StaticDispatch { static abstract class Human { } static class Man extends Human { } static class Woman extends Human {...原创 2019-03-01 19:51:58 · 196 阅读 · 0 评论 -
深入JVM 方法调用-解析
方法调用不等同于方法执行,方法调用阶段唯一的任务是确定被调用方法的版本,暂时不涉及内部的具体执行过程。在程序运行过程中,方法调用是最频繁的操作。但Class文件的编译过程并不包括传统编译的连接步骤,一切方法调用在Class文件里存储的都是符号引用,而不是方法在实际运行的内存布局的入口地址(相当于直接引用)。这个特性使得Java带来了强大的拓展能力,但也使得Java方法调用过程变得复杂起...原创 2019-02-27 16:43:34 · 215 阅读 · 0 评论 -
深入JVM GC收集算法概述
——标记-清除算法最基础的收集算法时“标记-清除”算法,算法分为标记和清除2个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,标记过程也就是之前的2次标记过程,该算法是最基础的算法,因为其它算法都是在其基础上进行改进算法主要不足:算法效率低下,标记和清除2个过程效率性能低下,另外空间也存在问题,标记清除后将产生大量的不连续的内存碎片,空间内存碎片太多导致之后需要分...原创 2019-02-22 21:53:45 · 163 阅读 · 0 评论 -
深入JVM GC对象的自救
Java虚拟机通过可达性分析等算法探测堆中不可达的对象,当一个对象通过可达性算法不可达时,并非立即被回收,而是暂时处于在“缓刑”状态,而真正要宣告一个对象死亡,必须经历至少2次标记过程——如果对象在进行可达性分析后发现与GC Roots引用链不相连时,那么它会被第一次标记并且进行一次筛选,筛选的条件是此对象是否需要执行finalize()方法。当对象没有覆盖finalize()方法,或者fin...原创 2019-02-22 21:05:12 · 410 阅读 · 0 评论 -
Java多线程 volatile synchronized关键字
多线程——一个程序可以包括多个子任务,可串行 / 并行——每个子任务可称为一个线程——如果一个子任务阻塞,程序可将CPU调度另一个子任务工作,确保CPU时间片获取率和使用时间 相较于多进程优势——线程间共享数据——线程间通讯更为高效——线程是轻量级的,切换更为方便——多个线程更易管理 Java多线程方法——java.lang.Thread ...原创 2019-02-18 10:41:18 · 202 阅读 · 1 评论 -
Java多线程 ForkJoin并发框架
Fork-Join多线程并发框架——JDK7提供的一种新的并发框架:分解、合并 基于分治递归的思想——适用于整体任务量不确定,但单个最小任务确定的情况使用 ForkJoin并发框架的主要类包括:ForkJoinPool:ForkJoin线程池,实现了ExecutorService接口和工作窃取算法,用于线程调度与管理。ForkJoinTask:ForkJoin任务,...原创 2019-02-18 10:41:09 · 420 阅读 · 0 评论 -
Java多线程 Executor并发框架
从JDK5开始提供Executor FrameWork (java.util.concurrent)——分离任务的创建和执行者的创建——线程可重复利用,降低new线程带来的消耗共享线程池——创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率——预先创建好一定的Thread放于池中,当要使用时可直接向池中获取——线程并发数量过多,抢占系统资源从...原创 2019-02-18 10:40:57 · 1223 阅读 · 0 评论 -
Java多线程 ThreadGroup线程组
线程组ThreadGroup——线程的集合 ——树状结构 大线程组可以包含小线程组——可以通过enumerate方法遍历组内的线程,执行操作——可管理组内线程,但效率低下,粒度不够精细——任务分配与执行过程耦合——线程重复创建关闭,开销较大 案例演示 Searcher类实现Runnable接口 重写run()方法 Result是一个简单的bean类...原创 2019-02-18 10:40:46 · 797 阅读 · 0 评论 -
深入JVM 可达性分析与引用分类
主流的程序设计语言(Java C#等)在确定回收对象的主流实现中,是通过 可达性分析(Reachability Analysis) 来判断对象是否存活。该算法的基本思路是通过一系列 GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Referance chain),当一个对象到GC Roots没有任何引用链(即GC Roots 到这些对象不可...原创 2019-02-21 15:07:13 · 502 阅读 · 0 评论 -
深入JVM 引用计数法
在堆中存放着对象实例,GC回收器在对堆进行回收前,需要确定哪些对象需要被回收,即确定哪些对象还存活,哪些对象已经死去(即不可能在被任何途径使用的对象)——引用计数法 前言:给对象添加一个引用计数器,每当一个地方引用它时,计数器加1,每当引用失效时,计数器减少1.当计数器的数值为0时,也就是对象无法被引用时,表明对象不可在使用,这种方法实现简单,效率较高,大部分情况下不失为一个有效的方法...原创 2019-02-21 14:42:50 · 1886 阅读 · 1 评论 -
深入JVM HotSpot算法实现
关于GC回收,主要设计对象存活判定算法和垃圾回收算法,而在经典的HotSpot虚拟机实现这些算法时,必须对算法实现细节进行严格约束,才能保证虚拟机高效执行。——枚举根节点从可达性分析中从GC Roots节点找引用链操作为例,可作为GC Roots节点主要在全局性的引用上(如常量或类的静态属性)与执行上下文(如栈帧中的本地变量表)。但是较大的引用程序仅仅方法区就数以百兆,如果逐个检查这些引用...原创 2019-02-23 14:33:45 · 263 阅读 · 0 评论 -
深入JVM 对象优先在Eden分配
前言:对象的内存分配,大方向讲,指的是对象在堆上分配,对象的主要分配发生在新生代的Eden区,当然少数分配在老年代,分配的规则并不是固定不变的,细节取决于具体的虚拟机实现。——对象优先在Eden区分配大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发生一次Minor GC虚拟机提供 -XX:PrintGCDetails这个收集器日志参数,告诉虚拟...原创 2019-02-23 15:46:47 · 2263 阅读 · 1 评论 -
深入JVM 长期存活对象将进入老年代
——长期存活对象进入老年代虚拟机采用分代收集的思想来管理内存,内存回收时必须识别哪些对象放入新生代,哪些对象放入老年代。为了做到这点,虚拟机为每个对象定义了一个对象年龄计数器。如果对象在Eden出生并经过一次Minor GC仍然存活,并且能被Survivor容纳,将被移动到Survivor区,并且对象年龄设置为1.对象每经过一次Minor GC后仍保持存活,年龄+1当对象年龄到达一定程...原创 2019-02-23 16:32:58 · 1718 阅读 · 0 评论 -
深入JVM 类加载-初始化
类的初始化阶段是类加载的最后一步,前面的类加载过程中,除了在加载阶段用户可以自定义类加载器参与外,其余动作由虚拟机完全控制和主导。到了初始化阶段,才真正开始执行类中定义的Java程序逻辑在准备阶段,部分变量已经赋予了一次系统要求的初始值,而在初始化阶段,根据程序设计者的主管计划去初始化类变量和其它资源,或者可以从另外一个角度表述:初始化阶段是执行类构造器<clinit()>方法的过...原创 2019-02-25 13:44:12 · 176 阅读 · 0 评论 -
深入JVM 解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程——符号引用:符号引用以一组符号来描述所引用的目标。符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可。符号引用与虚拟机1的内存布局无关,引用的目标不一定加载到内存中。各种虚拟机实现的内存布局不相同,符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中——直接引用:直接引用可以是直接指向目标的指针,相对偏...原创 2019-02-25 13:26:27 · 196 阅读 · 0 评论 -
深入JVM 类加载-验证
验证是连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合虚拟机的规范要求。Java语言本身是相对安全的语言,使用纯粹的Java代码无法做到访问数组边界以外的数据,将一个对象类型转化为未实现的类型,跳转到不存在的代码处,如果这样做,javac编译期间将拒绝编译。但是Class文件并不一定由Java语言编译而来,可以通过任何途径获取。在字节码语言层面,上述Java代码...原创 2019-02-25 13:06:58 · 827 阅读 · 0 评论