client 与 server
Created|Updated|Java
|Word Count:168|Reading Time:1mins|Post Views:
client 模式
默认的jit编译器,c1。
默认的gc:serial-serial old。
需要更短的启动时间和初始堆大小,能做更保守的优化。
默认-Xms是1M,-Xmx是64M。
适合 GUI 程序。
server 模式
默认的jit编译器,c2。
默认的gc:ps-serial old即 PS MarkSweep(可以启用parallel old)。
需要更长的启动时间和更大的堆大小,能够做更有深度的优化。
默认-Xms是128M,-Xmx是1024M。
适合长时间运转的程序。
64 位JVM#
在64位 JVM 上有个 -d64 的模式,实际上就是禁止client模式单独启动,只允许server模式或者混合编译模式启动的模式。
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles
2026-08-06
深入 Logstash 01 - 架构:JRuby、JVM 与 pipeline 的运行形态
.conf 里声明的每个插件都是 Ruby gem,但把这些插件串起来执行的已经不是 Ruby 代码。Logstash 8.x 没有 Ruby 执行引擎——8.0 把它整个移除了。.conf 先由 ConfigCompiler 编译成 PipelineIR,再编译成由 Dataset 节点组成的 Java 执行图,插件的 filter/encode 方法是被这张图通过 JRuby 的 Java 互操作回调的。 上一篇确立了 event 与三段管道(input → filter → output)的核心抽象。这一篇顺着上面这道落差往下看两件事:插件是 Ruby gem 却跑在 JVM 上,在启动开销、线程模型和内存账上分别意味着什么;一个进程里多条 pipeline 的结构又是如何组织的。 版本前提 本系列的示例基于 Logstash 8.x,参数名与默认值以 8.19 分支的源码为准。 有一个设置会影响几乎每一篇的实验输出:pipeline.ecs_compatibility。Logstash 8 起它的默认值是 v8,所有实现了 ECS 兼容模式的插件都按 Elastic Co...
2019-09-05
重述双亲委派模型
何时加载类 根据 Java 语言规范(JLS §12.4),类或接口在首次主动使用时才会被初始化。主动使用包括以下情况: 遇到 new、getstatic、putstatic、invokestatic 等字节码指令时。这些指令分别对应创建对象实例、读取或设置静态字段、调用静态方法。 对类进行反射调用时,如 Class.forName() 或 Method.invoke()。 初始化某个类的子类时,父类会先被初始化(但父类接口不会)。 虚拟机启动时会先加载设置的主类,即包含 main() 方法的类。 使用 java.lang.invoke 包的动态语言支持特性时,如 MethodHandle 调用。 需要注意的是,被动引用(如通过数组引用、常量引用、访问子类的静态字段等)不会触发类初始化。 从 Java 到 cpp 源码分析 双亲委派模型的工作流程 双亲委派模型的核心逻辑在 java.lang.ClassLoader.loadClass(String name, boolean resolve) 方法中: 123456789101112131415161718192021222...

2026-01-12
Java 并发编程笔记
本文思维导图总览: 下载思维导图源文件 写在前面的话 并发编程最早的实践都在操作系统里。高层语言的并发模型都要基于底层系统对硬件抽象和并发的设计来设计和实现,不能超出操作系统允许的范围。所谓的高级抽象总体上是简化对 OS 底层机制的复杂调用。 并发与异步 本文聚焦并发(Concurrency),即多任务在同一时间段内的交替或并行执行,核心问题是资源共享、线程同步与协作。 **异步(Asynchronous)**是另一维度:调用方发起操作后不等结果返回即继续执行,通过回调、Future或事件机制获取结果。异步可通过单线程事件循环实现,也可依托多线程并发实现。 二者关系:并发关注"多任务如何执行与协调",异步关注"调用是否阻塞等待"。并发编程常涉及异步,但本文不展开异步编程模式(如响应式流、协程),相关内容请参阅《Java 线程池笔记》。 管程 理论和实践之间是有鸿沟的,要弥合这种鸿沟,通常需要我们去学习别人的实践。比如并发的标准设计思想来自于操作系统里的管程(monitor),我们应当学习管程,进而了解标准的并发模型-管理共享变量和线程(并...
2017-10-23
昂贵的异常
抛出问题 Joshua Bloch 在《Effective Java》的 Item 57 里明确地提到过,不要试图用 Exception 的跳转来代替正常的程序控制流。他列举了很多原因,但特别提到了抛出异常会使得整个程序运行变慢。抛出异常远比普通的 return、break 等操作对控制流、数据流的性能影响要大,它就只适合拿来作异常分支的控制语句,而不能拿来编写正常的逻辑。 Throwing exception is expensive. 这句话在 Java 的程序员世界里面已经成为老生常谈,却很少有人谈及到底抛出异常比正常的程序跳转返回慢在哪里,有多慢。"不要滥用异常"好像一个猴子定律,人们知道不能这么做,却不明白为什么不能这么做。 此前读了一位同事写的好文《Java虚拟机是如何处理异常的》,深入地分析了 JVM 对异常跳转的处理过程:JVM 会通过异常表的机制,优化异常抛出和正常返回之间的性能差异。仅从程序计数器的移动上来讲,抛出一个异常对栈帧的弹栈并不比直接返回更昂贵。写在前头的结论是:"try-catch 语句块几乎不会影响程序运行性能!...
2026-05-21
进程启动期的静默故障:JVM 与 Node.js 的调试方法论
很多人都遇到过这种场景:一个 JVM 进程因为 -Xmx 写错了一个字符,启动起来就死掉,控制台一行日志都没有;一个 Node.js CLI 比如 opencode 在前台 hang 住,光标不闪,也不退出;一个 Spring Boot 服务被 systemd 拉起来,systemctl status 显示 running,但端口永远不开。stderr 看不到、源码也没有,只能反复重启。 这类问题的共同点不是程序"出 bug",而是进程在"出第一行日志"之前就已经失败或卡住。常规的"看日志找异常"那一套这时候没东西可看。需要的是另一类方法论:把进程当黑盒,从外部撬开它的状态。 一、先把"看不到日志"分成四种情况 把"启动期黑盒"展开来看,至少是四种性质完全不同的故障。混在一起调,方向就错了。 类别 特征 进程状态 主要工具方向 A. crash 静默 进程已经退出,但没看到任何 stderr 不存在 找输出去向;看 OS / runtime 留下的尸检文件 B....

2026-01-18
无锁队列
Java 一读一写(SPSC):Memory Barrier + Volatile 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657/** * Single-Producer Single-Consumer (SPSC) 无锁环形队列。 * * <p>原理说明: * - 仅允许一个线程调用 {@code offer()},一个线程调用 {@code poll()}。 * - 由于没有写竞争,无需 CAS;只需保证写操作对消费者可见。 * - 使用两个 volatile 索引(head/tail)建立 happens-before 关系: * 生产者写入元素 → volatile 写 tail → 消费者 volatile 读 tail → 读取元素。 * - 这本质上利用了 Java 内存模型中的“volatile 写-读”内存屏障(StoreLoad), * ...
