JVM基础 -- 伪泛型
本文将从JVM字节码的角度解释一下Java为什么是伪泛型
伪泛型
Java是伪泛型的,泛型在Java中只是语法糖,是通过类型擦除和强制转换来实现的
在运行期,ArrayList<Integer>与ArrayList<String>就是同一个类,在Java中并不存在类似与ArrayList<Integer>这种泛型类型
代码1234567891011121314151617181920public class FakeGeneric { static class Father { } static class Son extends Father { } private static void checkFather(Father father) { } public static void main(String[] args) { Map<Father, Father> map = new HashMap<&g ...
JVM基础 -- 方法重载 + 方法重写
本文将从JVM字节码的角度解释方法重载与方法重写
方法重载代码12345678910111213141516171819202122232425262728293031323334package me.zhongmingmao.test;public class StaticDispatch { interface Human { } static class Man implements Human { } static class Woman implements Human { } public static void sayHello(Human human) { System.out.println("Hello , I'm a human"); } public static void sayHello(Man man) { System.out.println("Hel ...
JVM基础 -- JVM字节码执行过程
本文将通过是实例简单介绍JVM字节码基于栈的执行过程
Stack Frame
一个方法从调用到执行完成,对应着一个栈帧(Stack Frame)在虚拟机栈(VM Stack)里面从入栈到出栈的过程
在编译成字节码期间,栈帧需要多大的局部变量表(Local Variable Table),多深的操作数栈(Operand Stack)都已经完全确定,并且写入到方法表的Code属性中
在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧关联的方法称为当前方法
局部变量表
用于存放方法参数和方法内部定义的局部变量
方法表中的locals属性记录了局部变量表的最大容量
局部变量表的存储单元为32-bit的slot,boolean、byte、char、short、int、float等会占用一个slot,long和double会占用两个slot
如果执行的是实例方法,那么第0个slot默认存储this
为了节省栈帧空间,slot是可重用的
操作数栈
方法表中的stack属性记录了操作数栈的最大深度
操作数栈可以容纳任意的Java数据类型,32-bit数据类型所占用的栈容量为1,64-bit数据 ...
JVM基础 -- JOL使用教程 3
本文将通过JOL分析Java对象的内存布局,包括伪共享、DataModel、Externals、数组对齐等内容代码托管在https://github.com/zhongmingmao/java_object_layout
伪共享Java8引入@sun.misc.Contended注解,自动进行缓存行填充,原始支持解决伪共享问题,实现高效并发,关于伪共享,网上已经很多资料,请参考下列连接:
https://yq.aliyun.com/articles/62865
http://www.cnblogs.com/Binhua-Liu/p/5620339.html
http://blog.csdn.net/zero__007/article/details/54951584
http://blog.csdn.net/aigoogle/article/details/41517213
http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/share/classes/sun/misc/Contended.java
代码12345678910111213 ...
JVM基础 -- JOL使用教程 2
本文将通过JOL分析Java对象的内存布局,包括Throwable、Class、Object Header、HashCode等内容代码托管在https://github.com/zhongmingmao/java_object_layout
Throwable代码12345678// JVM Args : -Djol.tryWithSudo=truepublic class JOLSample_07_Exceptions { public static void main(String[] args) throws Exception { out.println(VM.current().details()); out.println(ClassLayout.parseClass(Throwable.class).toPrintable()); }}
运行结果1234567891011121314151617# Running 64-bit HotSpot VM.# Using compressed oop with 3 ...
JVM基础 -- JOL使用教程 1
本文将通过JOL分析Java对象的内存布局,包括基本使用、字节对齐、实例域重排序、继承、继承栅栏、继承对齐等内容代码托管在https://github.com/zhongmingmao/java_object_layout
Maven依赖12345<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.8</version></dependency>
基本使用代码123456789101112// JVM Args : -Djol.tryWithSudo=truepublic class JOLSample_01_Basic { public static void main(String[] args) throws Exception { out.println(VM.current().details()); o ...
JVM基础 -- Instrumentation + sa-jdi 实例分析
本文将通过Instrumentation + sa-jdi来分析几个实例的内存对象布局
关键概念
Java对象的内存布局:对象头(Header) + 实例数据(Instance Data) + 对其填充(Padding)
Header具体内容
Mark Word:存储对象hashCode、锁信息等
Class MetaData Address:存储对象类型数据的指针
Array Length:数组的长度(如果当前对象是数组,否则没有这一内容)
HotSpot JVM中对象的对齐方式:8字节对齐
实例域重排序:为了节省内存空间,实例域将按(double/long,int/float,short/char,boolean/byte,reference)进行重排序
非静态内部类:有一个隐藏的对外部类的引用
指针压缩:影响对象的内存布局,JVM参数:-XX:+UseCompressedOops
指针压缩的影响
是否开启压缩
Mark Word
Class MetaData Address
Reference
否
8
8
8
是
8
4
4
指针压缩代码123456public cla ...
JVM基础 -- Instrumentation + sa-jdi 工具构建
本文首先介绍测量对象内存布局的其中一种方法,Instrumentation + sa-jdi
核心代码
代码托管在:https://github.com/zhongmingmao/java_object_layout
采用Instrumentation + sa-jdi的方式需要自己编写代码,比较繁琐,OpenJDK提供的JOL (Java Object Layout) 工具则是开箱即用,非常方便,后续博文会进一步介绍JOL的使用
测量对象大小通过Instrumentation测量对象占用的空间大小
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293/** * 对象占用字节大小工具类<br/> * see http://yueyemaitian.iteye.com/blog/2033046 ...
JVM基础 -- VirtualMachineError实例
VirtualMachineError有两个常见的实现类:StackOverflowError、OutOfMemoryError,本文将用代码分析几种情况的VirtualMachineError
JVM参数
内存区域
虚拟机栈VM Stack
堆Heap
方法区Method Area
共享/隔离
线程隔离
线程共享
线程共享
存放的数据
栈帧 Stack Frame
对象实例/数组
类信息、常量、静态变量等数据
异常情况
StackOverflowErrorOutOfMemoryError
OutOfMemoryError
OutOfMemoryError
JVM参数
-Xss
-Xms-Xmx
-XX:PermSize-XX:MaxPermSize-XX:MetaspaceSize-XX:MaxMetaspaceSize
注:在JDK8之前,Hotspot JVM采用永生代(Permanent Generation)来实现方法区(Method Area),从JDK8开始,已经移除了永生代,使用Metaspace进行替代,相关连接请参考:
http:/ ...
Vim -- 文件
本文将介绍Vim中的文件
基础文件、缓冲区和编辑会话文件:存储在磁盘上缓冲区:存在于内存中编辑会话:执行一次vim命令,默认显示第一个文件的缓冲区,其他文件的缓冲区为后台缓冲区
缓冲区列表一次编辑会话可以在多个缓冲区上工作,这多个缓冲区就是缓冲区列表
123456789101112131415161718192021222324252627# 展示缓冲区列表:ls:列出所有被载入到内存中的缓冲区列表 -:非活动的缓冲区 a:激活的缓冲区 h:隐藏的缓冲区 =:只读的缓冲区 +:已经修改但尚未写入磁盘的缓冲区 #:轮换缓冲区,通过<C-^>切换成当前缓冲区 %:当前缓冲区,通过<C-^>把当前缓冲区切换成轮换缓冲区 <C-^>:#与%切换# 遍历缓冲区列表bp[rev]:上一个缓冲区bn[ext]:下一个缓冲区bf[irst]:第一个缓冲区bl[ast]:最后一个缓冲区b[uffer] {N}:直接跳转到第{N}个缓冲区,例如:b 3b[uffer] {bufferNam ...