JVM拾遗(5): 对象大小计算

JVM拾遗(4): Java对象的创建及内存布局讲了JVM如何实例化对象以及对象在内存中的表示.
本次讲解如何计算一个对象的大小.

为啥要讲这个? 因为笔者在做一块业务的时候,老板有次让从数据库取100000条天气数据,在内存里按业务规则排序.
这明显不合理会让内存爆炸的需求,怎么怼回去呢?

这时候就要搬出我们的理论支持来计算一番了.

查看更多

JVM拾遗(4): Java对象的创建及内存布局

上一节JVM拾遗(3): 类装载机制讲了JVM如何将类装载到虚拟机以供后续使用
那么JVM是如何创建类的实例呢?该对象是如何分配内存的?

1. 实例化

1.1 创建对象的方式

Java对象的创建, 有多种方式,最简单就是new XXClass, 还可以通过反射xx.clone(),反序列化以及黑科技Unsafe.allocateInstance等方法.

new和反射创建对象实例的时候,会初始化实例字段.

如果类没有构造器,会默认添加构造器,并且编译成<init>方法.
默认生成的构造器里,如果父类有无参构造器, 会隐式递归调用父类的构造器.

查看更多

JVM拾遗(3): 类装载机制

上一篇我们了解了class文件结构, 那么JVM如何使用编译好的class二进制文件?

简言之: JVM会读取.class文件并加载和初始化到方法区, 之后才能被后续程序使用.
同时该过程还需要满足一些要求:

  • 加载的class文件不能影响虚拟机的稳定性, 也就是class文件要正确合法
    • java的rt.jar里定义的类,如java.lang.Object, 不能被替换
    • class文件里的各个符号引用要合法
  • 允许运行时添加功能, 如各种分析工具包(arthas)等

JVM是解释执行字节码的,不像c/c++那样编译的时候静态链接完了, 是在运行时期动态链接的。

查看更多

JVM拾遗(2): 平台无关性基石之Class解析

博客备案了一个月,中途也有各种工作的事情,现在继续更新。
前面从比较远的角度介绍了JVM的一些小常识, 如果没看懂也没关系,毕竟学习的过程就是
先感性认识,后才能升华到理性认识。所谓书读百遍其义自见也是类似的道理。

这次谈谈Java的平台无关性的基石: Class文件。

查看更多

JVM拾遗(1): 万米高空看JVM

开个新系列,本系列会对JVM的知识点拾遗, 也是对自己JVM学习的一个梳理。
关于JVM的方方面面都会讲到,应该会是理论为主,辅代码和图(不会是纯理论的)。

以前看过林林总总的JVM书籍,比如周志明大佬的<<深入理解Java虚拟机>>和张秀宏大佬的<<自己动手写Java虚拟机>>, 也跟着造了个小JVM,所以也尝试将知识整理下
本系列会比较长,但是会把知识点细分,前后贯通串起来。
如果没有特殊指出,JVM使用的是Hotspot VM,JDK使用的是OpenJDK8

查看更多

Java NIO分析(12): NIO总结

迟来的总结,NIO系列写了11篇了,本篇做个总结吧
写这个系列的起因是各个框架比如netty, tomcat, jetty这些高性能框架的
基石就是NIO, 一直想讲讲它们高性能的原因。

查看更多

Java NIO分析(11): 零拷贝技术以及NIO的支持

前面已经讲了Selector,SocketChannelDirectBuffer, 这些是NIO网络编程中最核心的组件
接下来我们会再讲几点非核心的优化(不代表不重要, 只是API不占NIO设计的大头):

  • 文件传输(File Transfer): 文件内容直接发送到网卡, 或者从网卡直接读到文件里
  • 内存映射文件(Memory-mapped Files): 将文件的一块映射到内存

这两项本质上都基于零拷贝(zero copy)技术。

查看更多

Java NIO分析(10): JVM堆外内存利用改进: DirectBuffer详解

前面我们详细讲了Java NIO分析(8): 高并发核心Selector详解Java NIO分析(9): 从BSD socket到SocketChannel, 分别是NIO的事件分发器和非阻塞处理器.

为了支持Channel的双向读写和Scatter/Gather操作,我们还需要Buffer,将I/O数据存储备用。普通的Buffer都是JVM堆内的Buffer, 比较好理解.

接下来我们聊聊JVM使用堆外内存的沧桑历史以及为什么要设计出DirectBuffer

查看更多

Java NIO分析(9): 从BSD socket到SocketChannel

前面我们讲了高并发核心Selector的源码分析,看到其对操作系统I/O多路复用的简单封装。
有了I/O多路复用之后,我们还需要非阻塞的socket读写操作.

因为内核告诉你A连接有数据可读,你想要读1K, 事实上只读到了0.5K, 如果使用传统的
socket API, 那么进程或者线程会在这里阻塞,浪费了CPU的时钟周期和珍贵的线程资源。
使用非阻塞就能在没有读满之前立刻返回,数据先放内存里,然后继续读下一个B连接的数据。

SocketChannel就是NIO对于非阻塞socket操作的支持的组件,其在socket上封装了一层, 所以我们先从Socket API说起。

查看更多

Java NIO分析(8): 高并发核心Selector详解

上节Java NIO分析(7): NIO核心之Channel,Buffer和Selector简介介绍了ChannelBufferSelector的基本用法
有了感性认识之后,来看看Selector的底层是如何实现的。

1. Selector设计

笔者下载得是openjdk8的源码, 画出类图

比较清晰得看到,openjdk中Selector的实现是SelectorImpl,
然后SelectorImpl又将职责委托给了具体的平台,比如图中框出的linux2.6以后才有的EpollSelectorImpl, Windows平台则是WindowsSelectorImpl, MacOSX平台是KQueueSelectorImpl.

从名字也可以猜到,openjdk肯定在底层还是用epoll,kqueueiocp这些技术来实现的I/O多路复用。前面 Java NIO分析(3): I/O多路复用之select系统调用 ,Java NIO分析(4): I/O多路复用之poll系统调用 , Java NIO分析(5): I/O多路复用之epoll系统调用写了3篇来说明其用法,感兴趣的读者可以回头看看。

查看更多