ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。
简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。
Atomic包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引用类型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。
内存溢出 OutOfMemory,指程序在申请内存时,没有足够的内存空间供其使用。
内存泄露 Memory Leak,指程序在申请内存后,无法释放已申请的内存空间,内存泄漏最终将导致内存溢出。
1、 增加两个参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof,当 OOM 发生时自动 dump 堆内存信息到指定目录
2、 同时 jstat 查看监控 JVM 的内存和 GC 情况,先观察问题大概出在什么区域
3、 使用 MAT 工具载入到 dump 文件,分析大对象的占用情况,比如 HashMap 做缓存未清理,时间长了就会内存溢出,可以把改为弱引用
当young gen中的eden区分配满的时候触发MinorGC(新生代的空间不够放的时候).
能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。
魔数: 确定这个文件是否为一个能被虚拟机接收的 Class 文件。Class 文件版本 :Class 文件的版本号,保证编译正常执行。常量池 :常量池主要存放两大常量:字面量和符号引用。访问标志 :标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。当前类索引,父类索引 :类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。接口索引集合 :接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按implents(如果这个类本身是接口的话则是extends) 后的接口顺序从左到右排列在接口索引集合中。字段表集合 :描述接口或类中声明的变量。字段包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。方法表集合 :类中的方法。属性表集合 :在 Class 文件,字段表,方法表中都可以携带自己的属性表集合。
notify() 方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。
1、 Class 文件包含了 Java 虚拟机的指令集、符号表、辅助信息的字节码(Byte Code),是实现跨操作系统和语言无关性的基石之一。
2、 一个 Class 文件定义了一个类或接口的信息,是以 8 个字节为单位,没有分隔符,按顺序紧凑排在一起的二进制流。
3、 用 "无符号数" 和 "表" 组成的伪结构来存储数据。
4、 无符号数:基本数据类型,用来描述数字、索引引用、数量值、字符串值,如u1、u2 分别表示 1 个字节、2 个字节
10、 表:无符号数和其他表组成,命名一般以 "_info" 结尾
组成部分
1、 魔数 Magic Number
Class 文件头 4 个字节,0xCAFEBABE
作用是确定该文件是 Class 文件
2、 版本号
4 个字节,前 2 个是次版本号 Minor Version,后 2 个主版本号 Major Version
从 45 (JDK1.0) 开始,如 0x00000032 转十进制就是 50,代表 JDK 6
低版本的虚拟机跑不了高版本的 Class 文件
3、 常量池
常量容量计数值(constant_pool_count),u2,从 1 开始。如 0x0016 十进制 22 代表有
21 项常量
每项常量都是一个表,目前 17 种
特点:Class 文件中最大数据项目之一、第一个出现表数据结构
4、 访问标志
2 个字节,表示类或接口的访问标志
5、 类索引、父类索引、接口索引集合
类索引(this_class)、父类索引(super_class),u2
接口索引集合(interfaces),u2 集合
类索引确定类的全限定名、父类索引确定父类的全限定名、接口索引集合确定实现接口
索引值在常量池中查找对应的常量
6、 字段表(field_info)集合
描述接口或类申明的变量
fields_count,u2,表示字段表数量;后面接着相应数量的字段表
9 种字段访问标志
7、 方法表(method_info)集合
描述接口或类申明的方法
methods_count,u2,表示方法表数量;后面接着相应数量的方法表
12 种方法访问标志
方法表结构与字段表结构一致
8、 属性表(attribute_info)集合
class 文件、字段表、方法表可携带属性集合,描述特有信息
预定义 29 项属性,可自定义写入不重名属性
首先通过 Javac 编译器将 .java
转为 JVM 可加载的 .class
字节码文件。
Javac 是由 Java 编写的程序,编译过程可以分为:① 词法解析,通过空格分割出单词、操作符、控制符等信息,形成 token 信息流,传递给语法解析器。② 语法解析,把 token 信息流按照 Java 语法规则组装成语法树。③ 语义分析,检查关键字使用是否合理、类型是否匹配、作用域是否正确等。④ 字节码生成,将前面各个步骤的信息转换为字节码。
字节码必须通过类加载过程加载到 JVM 后才可以执行,执行有三种模式,解释执行、JIT 编译执行、JIT 编译与解释器混合执行(主流 JVM 默认执行的方式)。混合模式的优势在于解释器在启动时先解释执行,省去编译时间。
之后通过即时编译器 JIT 把字节码文件编译成本地机器码。
Java 程序最初都是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会认定其为"热点代码",热点代码的检测主要有基于采样和基于计数器两种方式,为了提高热点代码的执行效率,虚拟机会把它们编译成本地机器码,尽可能对代码优化,在运行时完成这个任务的后端编译器被称为即时编译器。
还可以通过静态的提前编译器 AOT 直接把程序编译成与目标机器指令集相关的二进制代码。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。