JVM/Java/Scala
JVM/Java/Scala
LittleMagics
Flinker @ JD.com
展开
-
JVM jmap命令的用法小结
jmap之前已经总结过了jstack命令的用法。今天周末,不想写长篇大论,来简单看看jmap命令。jmap是JVM自带的堆内存转储(heap dump)生成工具,可以用来分析某JVM进程的堆内存占用,以及所有对象的概况。其用法说明如下所示。~ jmap -helpUsage: jmap [option] <pid> (to connect...原创 2020-02-08 23:11:17 · 2083 阅读 · 0 评论 -
Java try-with-resources简介与其Scala workaround
在我们使用Java编写业务逻辑时,如果打开了一些由外部组件管理的资源(如文件、文件I/O流、数据库连接、网络连接等等),就必须在使用完这些资源之后,通过资源句柄手动关闭。如果不关闭的话,JVM并不会回收它们,就会出现文件被占用无法打开、数据库连接池耗尽等情况。以FileInputStream为例,传统的try-catch-finally写法如下:public class Reso...原创 2020-01-21 23:24:48 · 500 阅读 · 0 评论 -
浅谈Java 8 Lambda表达式背后的事儿
前言Java 8于2014年3月发布,距今已经快要过去6年了。虽然现在已经迭代到了Java 13,但根据JVM生态系统调查,在2018年年底,有79%的Java应用采用的仍然是Java 8。因为从Java 9往后变成了半年更新一次(只有11是LTS版),并且语言层面的变动比较大,生产环境兼容和迁移的成本太高,何况Java 8的特性也够用了。Java 8在当年是个极其重要的更新版...原创 2020-01-18 23:02:53 · 306 阅读 · 1 评论 -
聊聊CPU缓存、伪共享与缓存行填充
前言2019年的最后一篇技术文了(明天写总结),找个细碎的话题随便聊聊吧。本文的知识点在之前的文章中隐蔽地出现过。CPU缓存简介CPU高速缓存(cache)是现代中央处理器的必备部件。它位于CPU package内部,在金字塔形存储体系中,距离计算单元的距离是各存储部件中第二近的,存取速度也是第二快的,仅次于寄存器。CPU在读内存时,会先尝试从缓存读取,如果缓存未命中,再从...原创 2019-12-30 23:54:02 · 484 阅读 · 0 评论 -
使用JNA调用C/C++动态链接库
在编写Java程序时,我们偶尔会调用一些其他语言(主要是C和C++)写成的第三方库。它们多以.dll或.so文件的形式存在,称为动态链接库(dynamic link library),也经常称为本地库(native library)。最近工作中遇到了需要调本地库的需求,做个简单记录。传统方法自然是使用大名鼎鼎的JNI(Java Native Interface),步骤如下:在...原创 2019-12-23 22:30:56 · 1441 阅读 · 0 评论 -
浅谈Java的伪随机数发生器和线性同余法
前言生成伪随机数是用Java编程时的常见需求,本文简单讨论一下最常用的Random和ThreadLocalRandom这两个随机数类,顺便介绍线性同余法。Random话休絮烦,直接上源码。 private final AtomicLong seed; private static final long multiplier = 0x5DEECE66DL; ...原创 2019-12-17 23:57:26 · 1410 阅读 · 0 评论 -
JVM jstack命令用法及相关知识小结
前言很久没有写过与JVM相关的文章了。今天搬砖有点累,不太想啃源码,写一篇实用性比较强的吧。在日常工作中,我们如果遇到JVM方面的问题,一般是采用各种现成的工具辅助定位解决,如VisualVM、JProfiler、Eclipse MAT、Arthas等。但是,我们也有必要了解JVM原生提供的那些命令行工具,本文就针对常用的jstack命令做个简单的总结,顺便聊一些与Java线程...原创 2019-12-09 22:57:43 · 952 阅读 · 0 评论 -
简单说说Java serialVersionUID
今天忙了很多其他事情,时间不大够了,写一篇超短的,然后趁早休息。在编写Java代码时,如果我们的类实现了java.io.Serializable接口,刚开始总会弹出如下的提示。若我们在IDEA的Inspection选项中打开了对serialVersionUID的检查,那么在类名上按Alt+Enter(或Option+Return)就可以自动生成一个serialVe...原创 2019-12-04 23:07:39 · 413 阅读 · 0 评论 -
聊聊Java泛型类型擦除及Flink类型暗示(type hint)机制
类型擦除的表现先通过以下两个例子认识类型擦除(type erasure)。例子一代码很简单,但无法通过编译,提示两个方法签名冲突,因为擦除类型相同。如果去掉其中一个方法,反编译之后的代码如下。public void foo(List list) { }例子二这段代码会返回true。并且Java中只有List.class的写法,没有L...原创 2019-11-03 23:38:22 · 4085 阅读 · 0 评论 -
Java ConcurrentModificationException及fail-fast机制简析
前言最近还是很忙,写一些相对容易的大家都知道的知识点吧。ConcurrentModificationException(下文简称CME),即并发修改异常,是Java集合操作中常见的一种异常。本文通过示例及JDK源码分析产生CME的内部机制,并提出解决方法。CME的产生java.util包下很多集合的操作都可能会抛出CME,这里就以ArrayList为例。下面的程序产生包含1...原创 2019-10-31 23:03:04 · 335 阅读 · 0 评论 -
再谈JVM里的记忆集合
在之前的文章《通过HotSpot源码详解Java堆空间创建过程》中,曾经提到了HotSpot里的卡表(card table),并且说它是解决跨代引用问题的。当时限于篇幅,讲得很潦草,本文说得详细一点(但今天没时间读源码了,抱歉)。我们从JVM的环境中抽离出来,考虑一个独立的两分代内存模型。该模型已经运行了一段时间,经历了多次对象创建与GC的过程,如下图所示。其中G...原创 2019-10-26 19:22:13 · 1947 阅读 · 5 评论 -
Java对象都是在堆上分配内存吗?
为了防止歧义,可以换个说法:Java对象实例和数组元素都是在堆上分配内存的吗?答:不一定。满足特定条件时,它们可以在(虚拟机)栈上分配内存。JVM内存结构很重要,多多复习这和我们平时的理解可能有些不同。虚拟机栈一般是用来存储基本数据类型、引用和返回地址的,怎么可以存储实例数据了呢?这是因为Java JIT(just-in-time)编译器进行的两项优化,分别称作逃...原创 2019-10-14 23:50:08 · 619 阅读 · 0 评论 -
详解JVM堆外内存的分配和回收机制
前言写这篇文章的契机是前段时间在Flink社区大群里详细解答了一个问题。我们每天都会与JVM堆打交道(之前哪篇文章的开头也是这个来着)。但作为大数据工程师,我们对JVM的堆外内存(off-heap memory,英文资料中也常称为native memory)应该也是非常熟悉的,Spark、Flink、Kafka等这些鼎鼎大名的大数据组件都会积极地使用堆外内存,更底...原创 2019-08-28 23:43:34 · 2229 阅读 · 0 评论 -
注意System.currentTimeMillis()潜在的性能问题
System.currentTimeMillis()是极其常用的基础Java API,广泛地用来获取时间戳或测量代码执行时长等,在我们的印象中应该快如闪电。但实际上在并发调用或者特别频繁调用它的情况下(比如一个业务繁忙的接口,或者吞吐量大的需要取得时间戳的流式程序),其性能表现会令人大跌眼镜。直接看下面的Demo。public class CurrentTimeMillisPer...原创 2019-08-18 23:13:55 · 793 阅读 · 0 评论 -
说一说管程(Monitor)及其在Java synchronized机制中的体现
什么是管程管程首先由霍尔(C.A.R.Hoare)和汉森(P.B.Hansen)两位大佬提出,是一种并发控制机制,由编程语言来具体实现。它负责管理共享资源以及对共享资源的操作,并提供多线程环境下的互斥和同步,以支持安全的并发访问。“共享资源以及对共享资源的操作”在操作系统理论中称为critical section,即临界区。管程能够保证同一时刻最多只有一个线程访问与操作共享资源...原创 2019-08-12 21:25:05 · 669 阅读 · 1 评论 -
Java CAS机制的底层实现探究
上次搞JVM源码挑了块硬骨头(见《通过HotSpot源码详解Java堆空间创建过程》),结果憋出内伤。当时放话说一个月不碰JVM,掐指一算,今天正好一个月了。不过这次得悠着点儿,选个容易的话题说说。所谓CAS,即“比较与交换”(Compare-and-swap),是最常见的乐观锁实现方式,看官应该对这个概念很熟悉。一次CAS过程是原子的,包含3个操作数:需要访问的内存地址V;...原创 2019-07-25 23:01:36 · 224 阅读 · 0 评论 -
谈谈Maven依赖原则及如何解决Maven依赖冲突
前言Maven虽然已经诞生多年,但仍然是当前最流行的Java系项目管理工具之一。在使用Maven的过程中,比较常见也相对难解决的问题就是依赖冲突,Gradle和sbt也同样存在此问题。本文先简述Maven中的依赖原则,然后通过两个例子讲述解决方法。Maven依赖原则Maven具有传递依赖(transitive dependency)的特性,即如果组件A依赖组件B,组件B依赖组...原创 2019-06-27 21:15:48 · 1807 阅读 · 1 评论 -
通过HotSpot源码详解Java堆空间创建过程
前言我们每天都在与Java堆打交道,对它的组成与调优都有了比较深刻的理解。Java堆的简单示意图如下。JDK 7-还是永久代(Perm),JDK 8+就是元空间(Metaspace)了不过,你有没有想过堆空间到底是怎么产生的呢?要搞清楚这个问题,就得通过阅读JVM的源码来追根究底了。本文分析的是OpenJDK 7u版本的源码,OpenJDK源码可以在其非官方的Gi...原创 2019-06-24 22:49:15 · 441 阅读 · 0 评论 -
通过源码理解Java类加载机制与双亲委派模型
前言在JVM中,类加载的过程分为加载、链接(验证、准备、解析)、初始化5个阶段。而加载阶段需要完成的重要事项之一,就是通过一个类的全限定名来获取定义此类的二进制字节码流(在HotSpot中,最常见的方法就是从class文件读取),并构造出类的定义。HotSpot并没有在内部直接做这件事,而是在外部提供了类加载器ClassLoader,让应用程序自己来决定如何获取和加载需要的类,...原创 2019-06-08 22:17:35 · 146 阅读 · 0 评论 -
为什么说枚举是最好的Java单例实现方法?
很久没有写过接地气的东西了,今天随便写一个非常基础的。其实这篇文章也可以叫做《Java单例的破坏与防御方法》,无所谓了。讲解Java单例实现方式及其原理的文章数不胜数,本文就不再多废话。在实际生产环境中,以下3种方式最常用,先复习一下。看官也可以试试能不能不参考任何资料,将下面的问题都回答正确。Java单例的三种经典实现双重检查锁(DCL)public class Doub...原创 2019-05-29 23:38:08 · 246 阅读 · 0 评论 -
调优IntelliJ IDEA的JVM参数
古人说得好,工欲善其事,必先利其器,这篇小随笔其实很久之前就该写了(因为是很久之前做的事情了)。现在为了写它,还得手动复现当时的场景,真麻烦呐。笔者的机器配置和环境如下:Intel Core i7-4870HQ, 4C/8T @ 2.5~3.7GHz16GB DDR3L 1600MHz RAM512GB PCIe SSDmacOS Mojave 10.14.4Inte...原创 2019-05-24 22:49:45 · 1208 阅读 · 0 评论 -
使用Arrays.asList()方法时的注意事项
最近休五一假期,不是很想写长篇大论,因此最近三篇文章都是信手拈来的小总结。等假期结束开工之后自然会恢复正常。java.util.Arrays.asList()方法是我们在日常工作中极其常用的方法之一,它可以方便地将数组类型转化为列表类型。例如:String[] teamsArray = { "Liverpool", "Man Utd", "Man City", "Arsenal...原创 2019-05-03 10:27:46 · 243 阅读 · 0 评论 -
Scala中下划线“_”的用法小结
下划线符号“_”在Scala语言中经常会用到,并且出现的场景千变万化。本文就列举出在一些主流情境下,“_”这个魔法符号分别是什么用法。匿名函数参数占位符当匿名函数传递给方法或其他函数时,如果该匿名函数的参数在=>的右侧只出现一次,那么就可以省略=>,并将参数用下划线代替。这对一元函数和二元函数都适用。例:scala> val list = List(5...原创 2019-05-02 21:39:40 · 1479 阅读 · 0 评论 -
简单易懂的现代魔法:Java sun.misc.Unsafe类探秘
《简单易懂的现代魔法》(よくわかる現代魔法)是日本小说家、原软件工程师樱坂洋撰写,宫下未纪插画的轻小说系列。小说讲述了在东京都银座,笨拙加上幼儿体形的女高中生森下历美,为了改变没有任何长处的自己,在看到魔法学校的传单后决定学习魔法(コード,Code)的故事。在魔法学校,她遇到了当今最强的魔法使……不好意思拿错剧本了。Unsafe类简介在之前我写的某篇讲解Spark...原创 2019-04-16 22:47:19 · 359 阅读 · 0 评论 -
由一件趣事快速复习Maven基础知识
刚才吃晚饭喝了两罐好德啤(链接https://item.jd.com/4085005.html,非广告),一时间有点飘飘欲仙,不太能集中注意力,不知道该写些什么。这时@小阿妩忽然发问了:——“我有个问题,你们撸代码的时候是怎样把那么多代码合在一起的啊”——“可以用IDE建项目,通过项目就能管理很多代码了”——“不太懂,你演示给我看看”于是我打开IDEA,新建了一个Mav...原创 2019-04-07 22:18:45 · 153 阅读 · 0 评论 -
以LinkedBlockingQueue为例浅谈阻塞队列的实现
目录阻塞队列简介阻塞队列的定义Java中的阻塞队列LinkedBlockingQueue单链表定义锁和等待队列容量和计数入队操作出队操作需要操作双锁的情况生产者-消费者问题示例一个小(?)问题最近在阅读Spark源码的过程中,又重新接触到了一些Java并发方面的知识,于是就见缝插针地将它们记录下来,当做复习与备忘。阻塞队列简介阻塞...原创 2019-04-01 22:53:32 · 394 阅读 · 0 评论 -
JVM字符串常量池及相关知识的再探究
JVM中的字符串常量池是个有些玄幻的玩意儿,关于它的细节,各类书籍和网站上众说纷纭。本文试图参考尽量权威的资料,找一个切入点来理清这团乱麻。所有参考文档均有传送门。本文提到的JVM就是HotSpot。如果不特别说明,JDK版本默认采用1.8,涉及到对比时会用1.6和1.7。字符串驻留字符串驻留(String interning)是字符串常量池产生的根本原因。英文维基上提供了非...原创 2019-03-07 23:48:09 · 516 阅读 · 1 评论 -
SimpleDateFormat线程不安全问题与ThreadLocal原理
SimpleDateFormat是JDK中长久以来自带的日期时间格式化类,但是它有线程安全性方面的问题,使用时要避免它带来的影响。SimpleDateFormat是线程不安全的写一个SimpleDateFormat在并发环境下简单的例子先。public class SimpleDateFormatExample { private static SimpleDateF...原创 2019-02-21 18:38:11 · 440 阅读 · 0 评论 -
使用maven-assembly-plugin插件自定义项目打包
在Maven中,主要有3个插件可以用来打包:maven-jar-plugin,默认的打包插件,用来打普通的project JAR包;maven-shade-plugin,用来打可执行JAR包,也就是所谓的fat JAR包;maven-assembly-plugin,支持自定义的打包结构,也可以定制依赖项等。我们日常使用的以maven-assembly-plugin为最多...原创 2019-02-18 20:41:38 · 437 阅读 · 0 评论 -
结合JVM深入理解Java字符串
既然题目里就提到了JVM,那么首先必然要奉上两张图。来自阿里《码出高效:Java开发手册》来自《深入理解Java虚拟机(第二版)》HotSpot JVM内存模型已经是老生常谈的知识了,所以这里也就不再赘述。直接说String。在String类的JavaDoc开头,就有这样一句话:Strings are constant; their valu...原创 2019-02-12 23:35:16 · 213 阅读 · 0 评论 -
深入理解Java的==操作符与equals()方法
==操作符对于8种基本类型(即boolean/char/byte/short/int/long/float/double):比较两个变量的值是否相等;对于引用类型(即除去8种基本类型外的其他所有类型):比较两个变量的引用内存地址是否相等。equals()方法Object类中的默认实现是直接用==的,也就是比较this和obj的引用内存地址是否相等。 public b...原创 2019-02-10 20:38:54 · 281 阅读 · 0 评论