JVM基础 -- 类加载
引用类型 类(字节流) 接口(字节流) 数组类(由JVM直接生成) 泛型参数(类型擦除,伪泛型) 类加载过程加载 加载:查找字节流,并且据此创建类的过程 对于数组类,没有对应的字节流,而是由JVM直接生成的 对于其他类而言,JVM需要借助类加载器来完成查找字节流的过程 类加载器 启动类加载器(boot class loader):由C++实现,没有对应的Java对象,在Java中只能用null来指代 除了启动类加载器外,其他的类加载器都是java.lang.ClassLoader的子类,有对应的Java对象 这些类加载器需要先由另一个类加载器(如启动类加载器),加载至Java虚拟机中,方能执行类加载 双亲委派模型 每当一个类加载器接收到加载请求时,会先将请求转发给父类加载器 在父类加载器没有找到所请求的类的情况下,该类加载器才会尝试自己加载 Before Java9 启动类加载器(boot class loader):负责加载最基础、最重要的类(-Xbootclasspath) 扩展类加载器(extension class loader):父类加载器为启动类加载器,负责加载相对次要、...
JVM基础 -- 基本类型
boolean类型Java代码1234567public class Foo { public static void main(String[] args) { boolean flag = true; if (flag) System.out.println("Hello, Java!"); if (flag == true) System.out.println("Hello, JVM!"); }} 编译运行12345$ javac Foo.java$ java FooHello, Java!Hello, JVM! 修改字节码运行12# jasm与javap的输出比较类似$ java -cp ./asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.bak 12345678910111213141516171819202122$ tail -n 23 Foo.jasm.bak...
JVM基础 -- 运行过程+运行效率
虚拟机视角 将class文件加载到JVM中,加载后的Java类会被存放在方法区,实际运行时,虚拟机会执行方法区内的代码 JVM同样会将内存划分出堆和栈来存储运行时数据,栈会细分本地方法栈和Java方法栈 PC寄存器:用于记录各个线程的执行位置 在运行过程中,每当调用进入一个Java方法,JVM会在当前线程的Java方法栈中生成一个栈帧 栈帧用于存放局部变量表和操作数 栈帧的大小是提前计算好的,并且JVM不要求栈帧在内存空间里连续分布 当退出当前执行的方法时,不管是正常返回还是异常返回,JVM都会弹出并舍弃当前线程的当前栈帧 硬件视角 Java字节码无法直接执行,需要JVM将字节码翻译成机器码,有两种形式:解析执行+即时编译 解释执行:逐条将字节码翻译成机器码并执行,无需等待编译 即时编译(JIT):将一个方法中包含的所有字节码编译成机器码后再执行,实际运行速度更快 HotSpot默认采用混合模式,先解析执行 字节码,然后将其反复执行的热点代码,以方法为单位 进行即时编译 即时编译建立在2-8定律的假设之上 对于占据大部分的不常用代码,无需耗费时间将其编译成机器码,而是采用解释执行的...
Kafka -- 消费者
基本概念消费者 + 消费者群组 消费者从属于消费者群组 一个消费者群组里的消费者订阅的是同一个主题,每个消费者接收主题的部分分区的消息 消费者横向扩展1个消费者 主题T1有4个分区,然后创建消费者C1,C1是消费者群组G1里唯一的消费者,C1订阅T1 消费者C1将接收主题T1的全部4个分区的消息 2个消费者 如果群组G1新增一个消费者C2,那么每个消费者将分别从两个分区接收消息 假设C1接收分区0和分区2的消息,C2接收分区1和分区3的消息 4个消费者 如果群组G1有4个消费者,那么每个消费者可以分配到一个分区 5个消费者 如果群组G1有5个消费者,_**消费者数量超过主题的分区数量**_,那么有1个消费者就会被**闲置**,不会接收到任何消息 总结 往群组里增加消费者是横向伸缩消费能力的主要方式 消费者经常会做一些高延迟的操作,比如把数据写到数据库或HDFS,或者使用数据进行比较耗时的计算 有必要为主题创建大量的分区,在负载增长时可以加入更多的消费者,减少消息堆积 不要让消费者的数量超过主题分区的数量,多余的消费者只会被闲置 消费者群组横向扩展 Kafka设计的主要目标...
Kafka -- Avro + Twitter Bijection
Avro + Kafka Native API 比较繁琐 编译Schema 依赖于Avro实现自定义的序列化器和反序列化器 引入依赖12345<dependency> <groupId>com.twitter</groupId> <artifactId>bijection-avro_2.12</artifactId> <version>0.9.6</version></dependency> Schema路径:src/main/resources/user.json 123456789{ "type": "record", "name": "User", "fields": [ {"name": "id", "type": "int"...
Kafka -- Avro + Kafka Native API
Schema123456789101112131415{ "namespace": "me.zhongmingmao.avro", "type": "record", "name": "Stock", "fields": [ {"name": "stockCode", "type": "string"}, {"name": "stockName", "type": "string"}, {"name": "tradeTime", "type": "long"}, {&qu...
Kafka -- Avro入门
引入依赖12345<dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.8.2</version></dependency> 1234567891011121314151617<plugin> <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>1.8.2</version> <executions> <execution> <phase>generate-sources</phase> <goals> ...
Kafka -- 生产者
生产者概述 创建一个ProducerRecord对象,ProducerRecord对象包含Topic和Value,还可以指定Key或Partition 在发送ProducerRecord对象时,生产者先将Key和Partition序列化成字节数组,以便于在网络上传输 字节数组被传给分区器 如果在ProducerRecord对象里指定了Partition 那么分区器就不会做任何事情,直接返回指定的分区 如果没有指定分区,那么分区器会根据ProducerRecord对象的Key来选择一个Partition 选择好分区后,生产者就知道该往哪个主题和分区发送这条记录 这条记录会被添加到一个记录批次里,一个批次内的所有消息都会被发送到相同的Topic和Partition上 有一个单独的线程负责把这些记录批次发送到相应的Broker 服务器在收到这些消息时会返回一个响应 如果消息成功写入Kafka,就会返回一个RecordMetaData对象 包含了Topic和Partition信息,以及记录在分区里的偏移量 如果写入失败,就会返回一个错误 生产者在收到错误之后会尝试重新发送消息,几次之后如果还...
Kafka -- 集群安装与配置(Docker)
配置文件文件列表123$ tree.└── docker-compose.yml docker-compose.yml123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103version: '2'services: zk1: image: confluentinc/cp-zookeeper:latest hostname: zk1 container_name: zk1 restart: always ports: - "12181:2181" environment: ZOOKEEPER_SERVER_ID: 1 ZOOKEEPER_CLIENT_...
Kafka -- 集群安装与配置(Ubuntu)
单节点安装Java添加ppa12$ sudo add-apt-repository ppa:webupd8team/java$ sudo apt-get update 安装oracle-java8-installer1$ sudo apt-get install oracle-java8-installer 设置系统默认JDK1$ sudo update-java-alternatives -s java-8-oracle 下载解压Kafka12345$ mkdir ~/Downloads & cd ~/Downloads$ wget http://mirrors.hust.edu.cn/apache/kafka/2.0.0/kafka_2.11-2.0.0.tgz$ mkdir ~/kafka && cd ~/kafka$ kafka tar -xvzf ~/Downloads/kafka_2.11-2.0.0.tgz --strip 1 允许Kafka删除主题1234$ vim ~/kafka/config/server.properties# 添加delete...













