代码之旅

I love Coding !

Java虚拟机-虚拟机栈

在前面的Java虚拟机-内存布局一文中我们简单介绍了虚拟机栈:

  • java虚拟机栈是线程私有的,他与线程的声明周期同步。虚拟机栈描述的是java方法执行的内存模型。
  • 每个方法执行都会创建一个栈帧,栈帧包含局部变量表、操作数栈、动态连接、方法出口等。

本文将继续详细介绍虚拟机栈。

阅读全文 »

Java虚拟机-元空间

在HotSpot JVM(jvm 8以前)中,永久代中用于存放类和方法的元数据以及常量池,在Java中对应能通过反射获取到的数据,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。永久代是有大小限制的(启动时设置),因此如果加载的类太多,很有可能导致永久代内存溢出(java.lang.OutOfMemoryError: PermGen)。Java 8为了解决这一问题,彻底将永久代移除出了HotSpot JVM,将其原有的数据迁移至Java Heap或Metaspace(见参考【1】)。

阅读全文 »

Java虚拟机-TLAB

因为堆是全局共享的,因此在同一时间,可能有多个线程在堆上申请空间,那么,在并发场景中,如果两个线程先后把对象引用指向了同一个内存区域,那么对象的内存分配过程就必须进行同步控制。无论是使用哪种同步方案,都会影响内存的分配效率。

而Java对象的分配是Java中的高频操作,所有,人们想到另外一个办法(TLAB)来提升效率。

阅读全文 »

Java-String和intern方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class JavaStringTest {
public static void main(String[] args){
String str1 = "string";
String str2 = new String("string");
String str3 = str2.intern();

System.out.println(str1==str2);
System.out.println(str1==str3);

}
}
/**
* -------- output ----------
* false
* true
*/
阅读全文 »

Java OOM Error

OOM(OutOfMemoryError)是java工程师都会了解的一种异常,实质上,OOM并不是只有一种,一共有9种不同类型的OOM:

  • java.lang.OutOfMemoryError: Java heap space
  • java.lang.OutOfMemoryError: GC Overhead limit exceeded
  • java.lang.OutOfMemoryError: Permgen space
  • java.lang.OutOfMemoryError: Metaspace
  • java.lang.OutOfMemoryError: Unable to create new native thread
  • java.lang.OutOfMemoryError: reason stack_trace_with_native_method
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit
  • java.lang.OutOfMemoryError: Kill process or sacrifice child
  • java.lang.OutOfMemoryError: Direct buffer memory

不同的原因触发不同类型的OOM,每种OOM类型的解决方案也不同。

阅读全文 »

正则表达式速查

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

阅读全文 »

反编译分析Java枚举类型的实现

假设我们正在编写一个剪刀-布-石头游戏。我们可以使用三个任意整数(例如,0,1,2或88,128,168),三个字符串(“剪刀”,“布”,“石头”)来表示三个手势。主要缺点是我们需要检查程序中其他不可行的值(例如 3、"Rock"等)以确保正确性。

枚举是一种特殊类型,它为程序中的常量提供类型安全的实现。换句话说,我们可以声明一个类型的变量,它只接受预先定义的值。

阅读全文 »

Java注解

Annotations是一种元数据,其作用在于提供程序本身以外的一些数据信息,也就是说Annotation他不会属于程序代码本身,不参与逻辑运算,故而不会对原程序代码的操作产生直接的影响。

  • 为编译器提供辅助信息 — Annotations可以为编译器提供而外信息,以便于检测错误,抑制警告等.
  • 编译源代码时进行而外操作 — 软件工具可以通过处理Annotation信息来生成原代码,xml文件等等.
  • 运行时处理 — 有一些annotation甚至可以在程序运行时被检测,使用.
阅读全文 »

Java 反射

反射常被用于在程序运行时检查或修改其执行行为。

为什么要使用反射

反射可以在下面几点帮助我们

  • 扩展功能
    • 扩展已有类的功能,例如有些字段不支持访问或修改,可以使用反射扩展。
  • 类浏览器和可视化开发
    • 类浏览器需要枚举类的成员,广泛应用于可视化开发环境
  • 调试和测试工具
    • 调试器需要能够检查类的私有成员,测试工具会使用反射调用API。

反射的弊端

反射很强大,但是不要滥用,如果可以避免使用,尽量避免。当使用反射时,下面的问题需要注意。

  • 性能开销
    • 反射会动态地处理对象,导致JVM的优化不能进行,因此,要避免在性能敏感地地方使用反射。
  • 安全限制
    • 反射可能会与安全管理相互冲突。
  • 内部资源暴露
    • 反射可以访问private方法,这可能会带来意料之外的副作用。
阅读全文 »