
Java 开源研究
文章平均质量分 76
Java 开源研究
超人汪小建(seaboat)
公众号:【远洋号】,笔名seaboat,擅长工程算法、人工智能算法、自然语言处理、计算机视觉、架构、分布式、高并发、大数据和搜索引擎等方面的技术,大多数编程语言都会使用,但更擅长Java、Python和C++。平时喜欢编程、绘画、看书、写作和运动,擅长素描、篮球、跑步、游泳、健身和羽毛球等运动项目。崇尚技术自由,崇尚思想自由。出版书籍:《Tomcat内核设计剖析》、《图解数据结构与算法》、《图解Java并发原理》、《人工智能原理科普》。
展开
-
Tomcat的系统安全管理
Tomcat是一个Web容器,我们开发的Web项目运行在Tomcat平台,这就好比将一个应用嵌入到一个平台上面运行,要使嵌入的程序能正常运行,首先平台要能安全正常运行。并且要最大程度做到平台不受嵌入的应用程序影响,两者在一定程度上达到隔离的效果。Tomcat与Web项目也是要最大程度隔离,使Tomcat平台足够安全。我们先看看Tomcat可能存在哪些安全威胁。(1) 在web应用的jsp页原创 2014-10-20 19:58:21 · 4210 阅读 · 1 评论 -
多线程之Java线程阻塞与唤醒
线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题。如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节。在Java发展史上曾经使用suspend()、resume()方法对于线程进行阻塞唤醒,但随之出现很多问题,比较典型的还是死锁问题。如下代码,主要的逻辑代码是主线程启动线程mt一段时间后尝试使用suspend(原创 2014-12-06 18:58:01 · 14431 阅读 · 1 评论 -
Java并发——线程池原理
“池”技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实现类由不同厂商实现,数据库连接的建立和销毁都是很耗时耗资源的操作,为了查询数据库中某条记录,最原始的一个过程是建立连接、发送查询语句、返回查询结果、销毁连接,假如仅仅是一个很简单的查询语句,那么可能建立连接与销毁连接两个原创 2015-01-24 19:56:15 · 4832 阅读 · 2 评论 -
悲观的并发策略——Synchronized互斥锁
volatile既然不足以保证数据同步,那么就必须要引入锁来确保。互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁释放后才能重新进行竞争。对于java开发人员,我们最熟悉的肯定就是用synchronized关键词完成锁功能,在涉及到多线程并发时,对于一些变量,你应该会毫不犹豫地加上synchronized去保证变原创 2014-09-05 19:02:12 · 4699 阅读 · 0 评论 -
socket系列之socket服务端与客户端如何通信
上面已经分别介绍了ServerSocket跟Socket的工作步骤,并且从应用层往系统底层剖析其运作原理,我们清楚了他们各自的一块,现在我们将把他们结合起来,看看他们是如何通信的,并详细讨论一下他们之间相互通信的一些细节。借助图2-3-2-4,想象一下你正在大学课室上着电脑,你跟你另外两个朋友觉得老师讲得课很菜,没必要听,于是你们仨都各自打开浏览器冲浪,刚好你们访问了同一台服务器,假如你用的是原创 2014-12-07 21:50:20 · 3993 阅读 · 0 评论 -
socket系列之客户端socket——Socket类
假设TCP套接字服务器端已经建立好并正在监听客户端的连接了,那么客户端就可以通过Socket类来发起连接。客户端发起一个连接请求后,就被动地在等待服务器的响应。这个类同样位于java.net包中,包含很多方法用于建立连接,操作数据流等。客户端按以下几步进行工作:① 创建一个Socket实例,构造函数直接指定远程服务器IP跟端口,建立一个TCP连接。② 通过这个Socket实例的输入输出流进原创 2014-12-05 20:49:57 · 2433 阅读 · 2 评论 -
tomcat如何避免遭遇ClassNotFoundException
在Tomcat中为什么创建类加载器后马上就Thread.currentThread().setContextClassLoader(catalinaLoader)?这里主要是为了避免后面加载类时加载失败。下面将举一个典型的例子说明如何利用URLClassLoader加载指定的jar包,并且解析由此引出的加载失败问题。首先,定义一个提供服务的接口,并且打包成TestInterface.jar。原创 2014-10-19 00:31:29 · 7309 阅读 · 5 评论 -
Java并发框架——AQS之如何使用AQS构建同步器
AQS的设计思想是通过继承的方式提供一个模板让大家可以很容易根据不同场景实现一个富有个性化的同步器。同步器的核心是要管理一个共享状态,通过对状态的控制即可以实现不同的锁机制。AQS的设计必须考虑把复杂重复且容易出错的队列管理工作统一抽象出来管理,并且要统一控制好流程,而暴露给子类调用的方法主要就是操作共享状态的方法,以此提供对状态的原子性操作。一般子类的同步器中使用AQS提供的getState、s原创 2014-10-13 21:13:22 · 4428 阅读 · 1 评论 -
Java线程的CPU时间片
Java中线程会按优先级分配CPU时间片运行,那么线程什么时候放弃CPU的使用权?可以归类成三种情况:当前运行线程主动放弃CPU,JVM暂时放弃CPU操作(基于时间片轮转调度的JVM操作系统不会让线程永久放弃CPU,或者说放弃本次时间片的执行权),例如调用yield()方法。当前运行线程因为某些原因进入阻塞状态,例如阻塞在I/O上。当前运行线程结束,即运行完run()方法里面的任务。...原创 2018-04-29 10:04:17 · 6201 阅读 · 0 评论 -
怎么用弱引用实现内存泄漏检测
在Java中,引用分为强引用、软引用、弱引用和虚引用四种。强引用,代码中普遍存在的形式,例如常见的普通类new出对象后的引用。GC不会回收强引用的对象。软引用,软引用对象会在内存溢出异常之前进行回收,也就是说在内存富裕的情况下GC不回收软引用。它可通过SoftReference类实现。弱引用,弱引用对象会在下一次GC时被回收,也就是说不管内存富不富裕,当GC时都会回收弱引用。它可通过WeakR原创 2017-06-04 18:32:02 · 1580 阅读 · 0 评论 -
tomcat启动批处理——catalina.bat
这个批处理才是tomcat服务器启动跟关闭的核心脚本。其中包括。。。。(各种变量),此节将详细讲解这个批处理的逻辑。先看看第一部分脚本:********************************************************************************************if not ""%1"" == ""run"" goto main原创 2014-10-27 20:58:15 · 5266 阅读 · 0 评论 -
Java并发框架——什么是AQS框架
什么是AQS框架1995年sun公司发布了第一个java语言版本,可以说从jdk1.1到jdk1.4期间java的使用主要是在移动应用和中小型企业应用中,在此类领域中基本不用设计大型并发场景,当然也没有大型互联网公司使用java,因为担心它本身的性能。在互联网及服务器硬件迅猛的发展下,sun公司更加注重企业级应用方面,毫无疑问高并发是一个重要的主题,于是在J2SE5.0(jdk1.5)代号原创 2014-11-09 23:04:57 · 6740 阅读 · 0 评论 -
直接内存和堆内存谁快
前言直接内存大多时候也被称为堆外内存,自从 JDK 引入 NIO 后,直接内存的使用也越来越普遍。通过 native 方法可以分配堆外内存,通过 DirectByteBuffer 对象来操作。直接内存不属于 Java 堆,所以它不受堆大小限制,但是它受物理内存大小的限制。配置可以通过 -XX:MaxDirectMemorySize 参数来设置最大可用直接内存,如果启动时未设置则...原创 2018-05-30 08:25:35 · 3119 阅读 · 2 评论 -
tomcat启动批处理——startup.bat
从文件命名上看就知道这是一个启动批处理,这个批处理的主要功能就是为了找到另一个批处理catalina.bat,并且执行catalina.bat。一开始就用if "%OS%" == "Windows_NT" setlocal 判断系统是否为Windows_NT,如果是的话则使用setlocal命令,此命令表示之后所有对环境变量的改变只限于该批处理文件,要还原原先的设置可以执行endlocal,如原创 2014-10-23 19:56:57 · 5221 阅读 · 0 评论 -
服务器模型——从单线程阻塞到多线程非阻塞(上)
前言的前言服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分: * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进前言这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞、I/O处理的单线程与多线程角度探讨服务器模型。对于I/O,可以分原创 2017-12-22 09:21:12 · 1912 阅读 · 0 评论 -
乐观的并发策略——基于CAS的自旋
悲观者与乐观者的做事方式完全不一样,悲观者的人生观是一件事情我必须要百分之百完全控制才会去做,否则就认为这件事情一定会出问题;而乐观者的人生观则相反,凡事不管最终结果如何,他都会先尝试去做,大不了最后不成功。这就是悲观锁与乐观锁的区别,悲观锁会把整个对象加锁占为自有后才去做操作,乐观锁不获取锁直接做操作,然后通过一定检测手段决定是否更新数据。这一节将对乐观锁进行深入探讨。上节讨论的Synchr原创 2014-09-09 20:30:51 · 5905 阅读 · 3 评论 -
Tomcat中的ssl安全信道的实现
为了实现https协议通信,tomcat需要利用JSSE把SSL/TLS协议集成到自身系统上,通过上一节我们知道不同的厂商可以实现自己的JSSE,而tomcat默认使用的是以前sun公司开发实现的包而且由JDK自带。Tomcat实现http及https通信的基础是什么?其实http与https的不同就是在创建通信套接字服务器时的不同,http是没有任何加密措施的套接字服务器,而https是靠嵌原创 2014-11-03 23:46:31 · 4901 阅读 · 0 评论 -
Java多线程模型
谈到Java多线程就涉及到多线程的模型及Java线程与底层操作系统之间的关系。正如我们熟知,现代机器可以分为硬件和软件两大块,如图2-5-1-1,硬件是基础,软件提供实现不同功能的手段。而且软件可以分为操作系统和应用程序,操作系统专注于对硬件的交互管理并提供一个运行环境给应用程序使用,应用程序则是能实现若干功能的并且运行在操作系统环境中的软件。同样,线程按照操作系统和应用程序两层次可以分为内核线程原创 2014-11-08 22:50:22 · 6368 阅读 · 0 评论 -
编写一个简易的Java NIO Reactor库
开源地址https://github.com/sea-boat/net-reactor源码设计接收器Acceptor/** * * @author seaboat * @date 2016-08-25 * @version 1.0 * <pre><b>email: </b>849586227@qq.com</pre> * <pre><b>blog: </b>http://blog.cs原创 2016-12-28 09:17:17 · 5707 阅读 · 2 评论 -
Tomcat内核之Tomcat的类加载器
跟其他主流的Java Web服务器一样,Tomcat也拥有不同的自定义类加载器,达到对各种资源库的控制。一般来说,Java Web服务器需要解决以下四个问题:① 同一个Web服务器里,各个Web项目之间各自使用的Java类库要互相隔离。② 同一个Web服务器里,各个Web项目之间可以提供共享的Java类库。③ 服务器为了不受Web项目的影响,应该使服务器的类库与应用程序的类原创 2014-12-14 20:25:13 · 4967 阅读 · 0 评论 -
从JDK源码看StringBuffer
概况Java 中处理字符串时经常使用的 String 是一个常量,一旦创建后不能被改变。为了提供可修改的操作,引入了 StringBuilder 类,可看前面的文章《从JDK源码看StringBuilder》。但它不是线程安全的,只用在单线程场景下。所以引入了线程安全的 StringBuffer 类,用于多线程场景。总的来说主要是通过在必要的方法上加 synchronized 来实现线程安...原创 2018-06-03 16:28:05 · 768 阅读 · 0 评论 -
socket系列之服务器端socket——ServerSocket类
一般地,Socket可分为TCP套接字和UDP套接字,再进一步,还可以被分为服务器端套接字跟客户端套接字。这节我们先关注TCP套接字的服务器端socket,Java中ServerSocket类与之相对应,这个类主要用于如何在服务器端创建一个套接字服务,建立一个通信终端,被动地等待客户端的连接,一旦有数据进入被监听的端口,这个类将能接收这些数据。ServerSocket类位于java.net包中原创 2014-11-30 22:23:44 · 3534 阅读 · 0 评论 -
tomcat启动批处理——setclasspath.bat
除了上面两个批处理,还有一个比较重要的脚本,即是setclasspath.bat,它主要负责寻找、检查JAVA_HOME和JRE_HOME两个变量。********************************************************************************************if ""%1"" ==""debug"" goto nee原创 2014-10-31 22:15:53 · 3347 阅读 · 0 评论 -
Java线程状态
线程跟人类一样拥有自己的生命周期,一条线程从创建到执行完毕的过程即是线程的生命周期,此过程可能在不同时刻处于不同的状态,线程状态正是这小节的主题,线程到底有多少种状态?不同状态之间是如何转化的?对于线程的状态的分类并没有严格的规定,只要能正确表示状态即可,如图2-5-7-1,先看其中一种状态分类,一个线程从创建到死亡可能会经历若干个状态,但在任意一个时间点线程只能处于其中一种状态,总共包含五个原创 2014-11-29 19:03:17 · 3294 阅读 · 0 评论 -
Socket接收器——Acceptor
Acceptor是JIoEndpoint的内部类,主要的职责就是监听是否有客户端套接字连接并接收socket,再将socket交由任务执行者(Executor)执行。不断从系统底层读取socket,接着做尽可能少的处理(最好就是接收到后不做任何处理),最后扔进线程池。为什么强调要做尽可能少的处理?这里关系到系统性能问题,过多的处理会严重影响吞吐量。因为tomcat默认只有一个接收器(一条线程负责套原创 2015-02-01 19:47:35 · 3445 阅读 · 8 评论 -
Java对象在JVM中长啥样
前言Java 是门面向对象的开发语言,那么我们自己编写的 Java 类生成的对象是什么样的?它肯定保存在虚拟机的内存中,但它以怎样的结构来保存的呢?带着疑问往下看看。关于KlassJava 层的开发可能不太熟悉 Klass,但肯定熟悉 class,我们只要知道 Klass 是 class 在 JVM 中的表示即可,即 Java class 对应 JVM Klass。C++ 中的继承...原创 2018-05-12 08:14:50 · 1098 阅读 · 1 评论 -
Java并发框架——公平性
所谓公平性指所有线程对临界资源申请访问权限的成功率都一样,不会让某些线程拥有优先权。通过前面的CLH Node FIFO学习知道了等待队列是一个先进先出的队列,那么是否就可以说每条线程获取锁时就是公平的呢?关于公平性这里分拆成三个点分别阐述:① 准备入队列的节点,此情况讨论的是线程加入等待队列时产生的竞争是否公平,线程在尝试获取锁失败后将被加入等待队列,这时多个线程通过自旋将节点加入队列,所有原创 2015-01-09 20:58:11 · 2618 阅读 · 0 评论 -
Tomcat内核之ASCII解码的表驱动模式
我们知道Tomcat通信是建立在Socket的基础上,而套接字在服务器端和客户端传递的报文都是未经过编码的字节流,每8位组成1个字节,计算机以二进制为基础,这是由于使用晶体管的开合状态表示1和0,这样8个电晶体管就可以组成一个字节,这正是应用层使用的最小单位——字节。在通过Socket进行网络通信的程序中,假如我们在接收到报文时不知道通过什么编码才能正确解码,最好的办法就是用Socket最底层原创 2015-01-17 19:57:02 · 2757 阅读 · 0 评论 -
Java并发框架——AQS阻塞队列管理(二)——自旋锁优化
看Craig, Landin, and Hagersten发明的CLH锁如何优化同步带来的花销,其核心思想是:通过一定手段将所有线程对某一共享变量轮询竞争转化为一个线程队列且队列中的线程各自轮询自己的本地变量。这个转化过程由两个要点,一是构建怎样的队列&如何构建队列,为了保证公平性,构建的将是一个FIFO队列,构建的时候主要通过移动尾部节点tail实现队列的排队,每个想获取锁的线程创建一个新节点并原创 2014-12-21 21:49:10 · 3639 阅读 · 5 评论 -
基于若引用的内存泄漏检测
在Java中,引用分为强引用、软引用、弱引用和虚引用四种。强引用,代码中普遍存在的形式,例如常见的普通类new出对象后的引用。GC不会回收强引用的对象。软引用,软引用对象会在内存溢出异常之前进行回收,也就是说在内存富裕的情况下GC不回收软引用。它可通过SoftReference类实现。弱引用,弱引用对象会在下一次GC时被回收,也就是说不管内存富不富裕,当GC时都会回收弱引用。它可通过WeakRe原创 2016-07-19 09:27:11 · 3714 阅读 · 0 评论 -
jsp自动编译机制
总的来说,Jasper的自动检测实现的机制比较简单,依靠某后台线程不断检测JSP文件与编译后的class文件的最后修改时间是否相同,若相同则认为没有改动,但倘若不同则需要重新编译。实际上由于在Tomcat部署的项目的JSP可能引入了其他页面,或者引入了其他jar包,而且这些资源都可能是远程的资源,所以实际处理会比较复杂,同样要遍历检测这些引入的不同资源是否做了修改。 上图是一个形象的示意图,我们知原创 2016-04-07 09:56:01 · 10812 阅读 · 7 评论 -
Java内存模型
在多核时代,如何提高CPU的性能成为了一个永恒的话题,而这个话题的讨论主要就是如何定义一个高性能的内存模型,内存模型用于定义处理器的各层缓存与共享内存的同步机制及线程和内存交互的规则。 Java的世界也有属于它自己的内存模型,Java内存模型,即Java Memory Model,简称JMM。由于Java被定义成一种跨平台的语言,所以在内存的描述上面也要能是跨平台的,Java虚拟机试图定义一种统一的原创 2017-05-15 09:31:28 · 2570 阅读 · 2 评论 -
2018汇总Java并发核心篇
Java如何获取当前线程从Java到JVM到OS线程睡眠从Java到JVM到OS线程的优先级Java线程的CPU时间片Java线程的调度Java线程的状态乐观的并发策略——基于CAS的自旋悲观的并发策略——synchronized互斥锁从JDK源码角度看并发的原子性如何保证从 JDK 源码角度看 java 并发线程的中断JDK源码角度看并发锁的优化从JD...原创 2019-01-07 11:35:23 · 530 阅读 · 0 评论 -
类加载器的双亲委派及打破双亲委派
一般的场景中使用Java默认的类加载器即可,但有时为了达到某种目的又不得不实现自己的类加载器,例如为了达到类库的互相隔离,例如为了达到热部署重加载功能。这时就需要自己定义类加载器,每个类加载器加载各自的类库资源,以此达到资源隔离效果。在对资源的加载上可以沿用双亲委派机制,也可以打破双亲委派机制。一、沿用双亲委派机制自定义类加载器很简单,只需继承ClassLoader类并重写findClass方法即可原创 2016-06-30 08:52:26 · 14846 阅读 · 12 评论 -
Java并发框架——AQS之原子性如何保证?
在研究AQS框架时,会发现这个类很多地方都使用了CAS操作,在并发实现中CAS操作必须具备原子性,而且是硬件级别的原子性,java被隔离在硬件之上,明显力不从心,这时为了能直接操作操作系统层面,肯定要通过用C++编写的native本地方法来扩展实现。JDK提供了一个类来满足CAS的要求,sun.misc.Unsafe,从名字上可以大概知道它用于执行低级别、不安全的操作,AQS就是使用此类完成硬件级原创 2014-10-11 20:58:45 · 3648 阅读 · 0 评论 -
流量控制闸门——LimitLatch套接字连接数限制器
Tomcat作为web服务器,对于每个客户端的请求将给予处理响应,但对于一台机器而言,访问请求的总流量有高峰期且服务器有物理极限,为了保证web服务器不被冲垮我们需要采取一些措施进行保护预防,需要稍微说明的此处的流量更多的是指套接字的连接数,通过控制套接字连接个数来控制流量。其中一种有效的方法就是采取流量控制,它就像在流量的入口增加了一道闸门,闸门的大小决定了流量的大小,一旦达到最大流量将关闭闸门原创 2015-01-25 19:42:54 · 3949 阅读 · 2 评论 -
从操作系统内核看Java非阻塞IO事件检测
非阻塞服务器模型最重要的一个特点是,在调用读取或写入接口后立即返回,而不会进入阻塞状态。在探讨单线程非阻塞IO模型前必须要先了解非阻塞情况下Socket事件的检测机制,因为对于非阻塞模式最重要的事情是检测哪些连接有感兴趣的事件发生,一般会有如下三种检测方式。应用程序遍历socket检测如图所示,当多个客户端向服务器请求时,服务器端会保存一个socket连接列表,应用层线程对socket列表进行轮询尝原创 2016-09-18 12:10:05 · 7225 阅读 · 5 评论 -
服务器模型——从单线程阻塞到多线程非阻塞(下)
前言的前言服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分: * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进前言这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞、I/O处理的单线程与多线程角度探讨服务器模型。原创 2018-01-04 09:14:01 · 1252 阅读 · 0 评论 -
从JDK源码看Java并发特性
索引下前面写的篇关于从JDK源码看Java并发特性的文章 文章列表 从JDK源码角度看java并发的原子性如何保证 从JDK源码角度看java并发的公平性 从JDK源码角度看java并发线程的中断 从JDK源码角度看并发竞争的超时 从JDK源码角度看并发锁的优化 从JDK源码角度看线程的阻塞和唤醒 从JDK源码角度看线程池原理原创 2017-02-19 20:58:12 · 1433 阅读 · 0 评论 -
Java并发框架——AQS中断的支持
线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止。在java中要让线程安全、快速、可靠地停下来并不是一件容易的事,java也没有提供任何可靠的方法终止线程的执行。回到第六小节,线程调度策略中有抢占式和协作式两个概念,与之类似的是中断机制也有协作式和抢占式。历史上Java曾经使用st原创 2014-11-23 22:49:15 · 3508 阅读 · 1 评论