文章目录

  • 前言
  • JVM概述
    • JVM是什么?解决了什么问题?
    • JVM运行流程
    • JVM 与 JRE,JDK的关系
  • JVM内存结构
    • JVM区域划分
      • 程序计数器
      • 方法区
  • 类加载机制
    • 五个阶段
    • 加载
    • 验证
    • 准备
    • 解析
    • 初始化
    • 总结
    • 双亲委派模型
  • 垃圾回收内存管理
    • 什么是GC?如何判定谁是垃圾?
      • 1.引用计数 判定
      • 2.可达性分析
    • 内存回收算法
      • 1.标记-清除
      • 2.复制算法
      • 3.标记-整理
    • JVM中的回收算法
    • Minor GC 与 Full GC 的区别与触发条件
  • JVM线程与锁机制
    • 程序计数器与线程的关系
    • 偏向锁、轻量级锁、重量级锁的演化过程
  • 例子:对象的创建全过程 从new到内存分配(类加载->内存分配)
  • 参考文章

前言

本来要开始学习Spring的,但听说最好学框架之前先把JVM,HTTP协议全都捋一遍,除了有助于Spring学习外,更重要的是这俩面试也经常会被问到,所以我必须本着“喜欢探索知识的个性”来学习了。

JVM概述

JVM是什么?解决了什么问题?

JVM(Java Virtual Machine,Java虚拟机)通俗一点说是一个假装是计算机的程序,专门运行.java程序。拟人化说就是它像一个翻译+保姆+管家的综合体,它可以解决什么问题呢?
翻译:把你写的.java程序翻译成别人能看懂的.class字节码
保姆:管理内存,帮你清理垃圾(垃圾回收)
管家:跨平台运行(可以在不同的OS上运行)
专业点来说,JVM 是运行 .class 字节码文件的虚拟计算机,它屏蔽了底层操作系统和硬件的差异,实现“一次编写,到处运行”。

有句话说得好,凡是都需要对比一下友商,让我们看看C++的相关替代品是啥。
答:C++不需要这些,因为C++是编译型语言,编译之后变成了机器码,直接可以运行在操作系统上。编译型语言执行效率更高,时间消耗更少。 这么一看是不是感觉踢到钢板了? 其实不然,友商虽然不需要这个就可以执行,这是它高性能的优点但同时也是一个很大的缺点。因为没有管家帮它接触各类操作系统,也没有保姆帮他回收垃圾。这些都是C++的痛点。具体来说,对比表格如下

特性JavaC++
编译结果字节码(.class)机器码(.exe / .out)
是否依赖虚拟机是,JVM 才能运行否,编译后直接运行
是否跨平台是(因为 JVM 屏蔽平台差异)否(不同平台要重新编译)
内存管理自动垃圾回收(GC)手动管理(new/delete)
类加载运行时加载(类加载器)编译时静态链接,没“加载器”

JVM运行流程

  1. 编译阶段(helloworld.java -> helloworld.class) 开发时
  2. 类加载阶段(helloworld.class 被类加载器加载进内存 JVM进行验证->准备->解析->初始化) 看看你合法吗,合法给你分配住的地方,分配完了之后准备给我干活。
  3. 执行阶段(将字节码翻译为机器码)穿上工装开始干活
  4. 内存管理,干着干着发现你的空间怎么越战越大,得给你释放一下了(垃圾回收)

JVM 与 JRE,JDK的关系

这就像一家三口 JDK最大包含 JRE JRE包含JVM

名称作用举例说明
JVMJava虚拟机,运行字节码就是你写的程序在哪执行
JREJava运行环境,包含 JVM + 核心类库就像一个 Java 程序能跑的最小环境
JDKJava开发工具包,包含 JRE + 编译器(javac)等工具你写程序、编译、运行都靠它

JVM内存结构

JVM区域划分

为什么要有区域划分?答:不同区域的内存有着不同的功能便于高效管理。比如你买了房子,你得给安排洗手间,厨房,客厅,卧室一样。不同的空间有不同的职责。

程序计数器

程序计数器的作用是保存指令地址的地方
什么是指令?指令就是字节码,也就是我们的写的代码,代码都是有作用的所以转化为字节码后也就是指令了,用来命令CPU下一步该干啥。什么是指令地址?就是存储指令的地方,我们执行指令的时候需要先将指令一个个从内存中取出来。

前面的文章中说过,线程调度,主要也靠程序计数器恢复上下文。这里的程序计数器也是存储当前线程执行的指令地址,那么JVM的程序计数器和线程的是一个嘛?显然不是,可以理解JVM是总的程序计数器,是当前程序执行到哪了,而线程中存的则是当前线程执行到什么位置了。如果线程发生阻塞,在调度回来执行的时候方便恢复现场。

栈是存储局部变量和函数调用信息的地方。什么是局部变量,顾名思义是指只在一个范围内生效的变量(比如一个函数内定义的变量,for循环内部定义的变量if语句内部定义的变量) 函数调用信息:传入函数的实参,函数内部的局部变量,调用函数的位置等。栈的基本属性是先进后出,比如在递归或函数内部调用函数中最内层调用函数最先出来,最外层调用函数最后出来。举个例子,判断树高度的例子
假设树长这样
在这里插入图片描述

    public  int deep(TreeNode root,int x){if(root==null){return x;}int x1=deep(root.left,x+1);int x2=deep(root.right,x+1);return Math.max(x1,x2);}int h = deep(root,0)+1;

栈的最底部 会存储实参(3,0),局部变量(x1,x2)这里说的是节点值,了解存储的那些节点就行,实际上是存储的一个个引用。依次类推往上分别存储(9,1) ,但调用此节点时发现已经没有孩子节点了 直接返回高度1,因此底部会变为(3,0),(1,x2) 。随后右孩子入栈 分别往上存储(20,1),(15,2),(7,2).最终逐个出栈(这里是(15,2)先出栈)。

同样的有多个线程调用函数的话,每个线程内部也是都有栈的。

堆是占用内存较大的数据结构了,其内部主要存储 new出来的对象实例,以及对象内部的成员变量。注意堆在线程可就没有了,因为线程太小了。

public void f(){
HashMap<Integer,Integer> hsm = new HashMap<>();
}

那这个例子中hsm 存储在哪呢? hsm 是局部引用 所以会存储在栈中,这里分清引用和对象实例,引用指的是对象在堆的存储位置,对象实例则是对象本身。 这也顺便解释 对象传参时引用调用为什么会改变原始对象本身,因为传参时传的是对象的地址的引用,而修改时会修改对象在堆中的本身,所以引用调用会改变其本身。而值传递,是将值传参了,不会改变原有的值(我理解的,不知道对不对,但有一种引用情况除外,那就是String类型,传参传入String的引用时不会改变原始值,这是因为一旦操作String类型都会创建一个副本,所以不会改变原始值)。

理解不了 没关系 这里就记住
堆存储new的对象实例 和 内部的成员变量
局部变量或引用都存储在栈中

方法区

方法区存储的是类对象,但我喜欢叫类属性。因为更好理解,类对象不是指前面的对象的实例。而是一个类中结构是啥样的,比如里边的变量的类型,方法的类型,有哪些方法,名字叫什么等。

类加载机制

类加载机制是指 JVM 在运行期间,将 .class 字节码文件加载到内存中,并转换成 Class 对象的整个过程。也就是说,当你在代码里用 new User() 或 User.class 的时候,JVM 要确保这个类的字节码已经在内存中了,这个“确保 + 加载 + 准备 + 连接 + 初始化”的过程,就是类加载机制。

五个阶段

加载-验证-准备-解析-初始化

加载

干了什么? 读取字节码内,创建一个class对象,存进方法区,此class对象是后面你反射的基础
目的:将类的字节码读取到JVM内存

举例子来说,你在运行Java对象前需要先把说明书(字节码) 从硬盘搬进内存,才能参考它干活

验证

干了什么?检查.class文件是否符合规范,是否非法越界,引用了不存在的类。
目的:保证虚拟机安全的运行,防止恶意或错误字节码破坏

就像你拿到了这个说明书,你得检查是不是骗人的。

准备

给类的静态变量分配内存,并初始化默认值。注意是初始化默认值,不是初始化。默认值指的是(0/null/false) 这种
比如 int x = 3 不会初始化为3,而是初始化为0.

就像你租一间房,房东先给你空房子和床,等你入住时再布置和摆东西(下一步才赋值)

解析

把常量池中的符号引用转化直接引用
例如:User u = new User(); 在常量池里是个字符串 “User”,解析后才变成真正的方法地址、内存地址等。

提前把类中引用的类/字段/方法都找好,变成可执行的“具体地址”
你看到说明书说“点这里”(符号引用),你得先知道“这里”是哪里(真正的函数地址)

初始化

这是真正的初始化,给类中的静态变量初始化提前设定的值
房间准备好了,现在你把桌子椅子搬进来、墙上挂个画,开始“入住

总结

阶段干了什么目的是否常考
加载读取 .class → 生成 Class 对象把类搬进 JVM
验证校验字节码合法性防止非法破坏 JVM
准备给 static 字段分配内存 & 默认值建立“类模板”
解析符号引用 → 真实引用做好准备执行⚠️(次要)
初始化执行 <clinit> 初始化代码正式让类“准备就绪”

双亲委派模型

这个属于加载阶段的部分,为什么单独要拿出来说。因为这部分理解对于你学习java有着重要意义,劣势基础,最终成为大牛。。。好了不说废话,因为这部分面试喜欢问。它的目的是找.class文件。 因为.class的文件可能存放在多个地方。比如在JDK中,比如自定义的在项目目录中。 类加载器有三个,每一个负责不同的区域。就像外卖小哥,每个区域可能会安排一个外卖小哥。
1、BootStrapClassLoader【模拟线路类加载器】 负责标准库常用的类
2、ExtensionClassLoader【扩展类加载器】加载JDK扩展的类,很少用
3、ApplicationClassLoader【应用类加载器】负责我们在项目中自定义的类

工作流程:首先进入应用类加载器,此时他会检查扩展类加载器是否加载过了。没有则进入扩展类加载器,进入之后,也会判断是模拟线路类加载器加载过了,没有则进入模拟线路类加载器。 就是一句话,如果没被加载过会先到自己的父类加载器去加载

为什么这样设计?因为这保证加载类时的一致性,不会出现自定义的类和标准库的类重名了不知道加载哪个。这里会优先加载标准库的类。

垃圾回收内存管理

垃圾回收这些一直是由JVM自动判定并回收,所以我们接触的很少。但对比友商的程序员(C),这就是不得不接触的了,因为C语言追求高性能,这种垃圾回收一类的东西它不care,所以只能辛苦程序员来完成了。看到这里是不是心里宽慰了一些

什么是GC?如何判定谁是垃圾?

什么是垃圾回收?我们写程序new的对象 创建的变量这些只要不用了就是垃圾,但垃圾依然占用着内存,我们需要清理它并回收内存。但不能乱回收,比如一个对象明明你还有用你却给它扔了这样会有大问题。因此如何判定谁是垃圾成为了重中之重。

如何判定谁是垃圾?
在判定之前,我们要明确目标,内存区域中只有堆中占用空间最大且是最需要回收垃圾释放内存的地方。所以我们默认垃圾回收针对的是堆中的数据。
如何判定?

1.引用计数 判定

此方法不是用在java中,了解如何运作的就可。引用计数对每个对象实例都会增加一份额外的空间用来计数,注意是对象实例,不是引用。例如:

Result re = new Result()  \\这里re 是引用,Result是对象实例我们针对的是对象实例,那有人会问引用如何回收\\引用的生命周期更短,只要超过作用域或者被定为null就回收了。
Result re1 =re; \\Result()的计数是2.因为有两个指向它

当引用计数变为0时,就回收这部分内存。也就是说取消一个引用时,其计数器减一。
这种方法存在什么问题呢? 具体看代码注释

public class RefCountDemo {public Object instance = null; // 引用另一个对象public static void main(String[] args) {//此时第一个RefCountDemo();计数器为1RefCountDemo objA = new RefCountDemo();此时第二个RefCountDemo();计数器为1RefCountDemo objB = new RefCountDemo();// A 引用了 B 此时第二个RefCountDemo();计数器为2objA.instance = objB;// B 又引用了 A 此时A的计数器为1 此时第1个RefCountDemo();计数器为2objB.instance = objA;// 断开外部引用  objA = null;objB = null;// 此时 objA 和 objB 相互引用,引用计数 ≠ 0// 但它们已经无用了,GC 无法识别(引用计数法失效)}
}

此外 空间利用率低,因为每次new 一个对象你都要分配额外的空间去计数。

2.可达性分析

于是为了解决以上两个问题,Java决定另辟蹊径。
可达性分析(Reachability Analysis) 是一种判断对象是否“存活”的算法:
从一组称为 GC Roots 的根对象出发,沿着引用链向下搜索,能被访问到的对象就是“可达的”,不可达的对象则认为“已经死亡”,可以被垃圾回收。

工作流程:
从 GC Roots 出发
沿着所有引用向下搜索(广度或深度优先)
标记所有能访问到的对象为“活着”
未被访问到的对象则是“死对象”,可以被回收

GCRoots有那些来源?

GC Roots 来源说明
栈帧中的本地变量表方法调用中的局部变量,如 new 出来的对象引用
方法区中静态变量如 static 字段的引用
方法区中常量引用final 常量等
JNI 引用(本地方法)通过 C/C++ 引用的 Java 对象
活跃线程对象每个正在运行的线程本身

public class ReachabilityDemo {
public Object ref = null;

public static void main(String[] args) {ReachabilityDemo a = new ReachabilityDemo();ReachabilityDemo b = new ReachabilityDemo();a.ref = b;b.ref = a;// 外部断开引用a = null;b = null;// 现在 JVM 会触发 GC,能正确识别 a 和 b 都不可达(虽然互相引用)
}

}
以上例子中 首先从栈帧中的本地变量表 a,b开始扫描 ,发现 a 和b 都为null了,所以第一个和第二个ReachabilityDemo(); 都无法访问到,于是回收这部分空间。同时将引用也回收

内存回收算法

找完垃圾后,就需要清理,如何清理呢?(释放内存)

1.标记-清除

通过可达性分析找到要回收的对象后,我们直接对垃圾占用内存释放。面试遇到的话,理解性记忆,标记了就清除嘛不就是,谁是垃圾就清楚谁其他的我不管,这就是标记清除。这种存在什么问题呢? 猛地一看貌似没毛病啊不就是谁是垃圾,谁就要扔啊,难不成还不扔垃圾?道理是这样地,但问题是扔了垃圾你不收拾一下房间嘛? 也就是说清理了垃圾,但会变成碎片化内存,就是隔一段有一小快是空闲,这些小块加起来是很大地,但分配这样大地空间 我们却无法分配(因为空间分配必须是连续地)。所以清理垃圾必须也得收拾房间,要不然杂乱无章,每地方都有东西放,但却又放不下大点地东西。

2.复制算法

此算法就是解决以上问题,整理内存。首先将内存一分为二,一半用,一半备用。当清理垃圾时,会先将不是垃圾地内存地值复制到另一把中去。然后在讲这一半地所有空间全部清除,这样就释放了这一半地所有空间。 复制算法,面试遇到就要想到加了复制俩字,就说明他会整理内存,变聪明了。但此时又会有什么问题呢? 这我好像只能用一半空间啊,内存这么金贵好不容易申请到,却只能用一半(空间利用率低)。此外,每次都要从这个房间把东西搬过去,万一这个房间垃圾不多有用地很多,全搬过去好累地(复制开销较大)。

3.标记-整理

对于复制出现地问题,标记整理解决了一部分(空间利用率低) 如何做呢?它将不是垃圾的内存的值覆盖到前边时垃圾的内存哪里,注意后者的内存一定满足大于等于前者才可直接覆盖。随后对后面的元素直接释放。此方法问题还是没有解决需要复制的问题

JVM中的回收算法

上面每一种算法单拎出来发现都不够完美,所以JVM采用了三者的结合分代回收! 顾名思义,将不同的对象根据存在时间的长短分为辈分大的和辈分小的。然后将堆内存一分为二, 其一存放辈分大的,其二存放辈分小的。 其中第二部分,又分为两部分,一部分伊甸区,一部分时幸存区。话不多说直接偷张图(这篇图的作者讲的特别好,文章最后我会表明引用他文章的)
在这里插入图片描述

1.刚new出来的对象直接放到伊甸区。
2.如果伊甸区对象熬过了可达性分析,则就放入幸村区。
3.幸存区继续开熬,来回复制
4.经过多轮后,幸存区已经有资格放到老年区,此时放到老年区。

Minor GC 与 Full GC 的区别与触发条件

Minor GC 针对年轻代判定并回收垃圾
Full GC 指 JVM 对整个堆空间进行回收

项目Minor GCFull GC
作用范围仅年轻代(Eden + Survivor)整个堆(新生代 + 老年代 + 方法区)
触发条件年轻 区满了,需要分配新对象老年代满、System.gc()、元空间不足、CMS失败等
耗时较短(几十 ms)较长(几百 ms 或秒级)
是否会 Stop-The-World✅ 是✅ 是
是否影响用户体验轻微明显卡顿,尤其是 Full GC 频繁时
回收频率高频尽量少

JVM线程与锁机制

程序计数器与线程的关系

  1. 程序计数器(Program Counter Register)
    每条线程都有独立的程序计数器,是线程私有的内存空间。
    是 JVM 中唯一一个线程私有的内存区域。
    用来记录当前线程正在执行的字节码指令地址。
    如果当前正在执行的是 native 方法,则该计数器值为 undefined。

  2. 为什么线程私有?
    Java 是多线程语言,而 JVM 采用线程隔离的方式来执行多线程代码。每个线程需要知道自己执行到哪一行代码了,所以每个线程必须有自己的 PC 寄存器,否则线程切换后无法恢复上下文。

偏向锁、轻量级锁、重量级锁的演化过程

无锁
↓(第一个线程获取)
偏向锁
↓(出现竞争)
轻量级锁
↓(竞争激烈,阻塞)
重量级锁

1 偏向锁(Biased Lock)
特点:偏向于第一个获取锁的线程
无需 CAS(Compare-And-Swap)操作,无锁竞争
将线程 ID 记录在对象头中

使用场景:大量线程反复进入同步块但没有竞争的情况
触发升级:如果另一个线程试图获取这个锁,则撤销偏向 → 升级为轻量级锁

2 轻量级锁(Lightweight Lock)
特点:多线程交替进入同步块时使用,使用 CAS 实现乐观锁
没有线程阻塞,尝试加锁失败的线程会 自旋 等待锁释放
使用场景:短时间同步,线程竞争不激烈(两个线程交替进入)
触发升级:如果 CAS 多次失败,自旋多次未成功 → 升级为重量级锁

3 重量级锁(Heavyweight Lock)
特点:使用操作系统 Mutex 来实现(synchronized 的早期实现)会使线程阻塞挂起和唤醒
问题:线程挂起、恢复的上下文切换代价非常大

例子:对象的创建全过程 从new到内存分配(类加载->内存分配)

public class JVMExample {public static void main(String[] args) {System.out.println("程序启动");User user = new User("Alice", 28);user.printInfo();user = null; // 使对象变为垃圾System.gc(); // 主动调用 GC(并不一定立即执行)System.out.println("程序结束");}
}class User {private String name;private int age;public User(String name, int age) {this.name = name; // 存在于堆中对象的属性this.age = age;}public void printInfo() {String info = "用户:" + name + ",年龄:" + age;System.out.println(info);}@Overrideprotected void finalize() throws Throwable {// finalize 可能被 GC 调用(不保证一定被调用)System.out.println("User 对象正在被 GC 回收!");}
}

1.类加载过程

阶段说明
加载从 .class 文件中加载字节码进方法区(元空间)
验证校验字节码正确性(如格式、指令合法)
准备分配静态变量的内存,并赋默认值
解析将常量池中符号引用替换为直接引用(如方法、字段地址)
初始化执行类的 <clinit> 静态初始化块或静态变量赋值

2.内存分配

区域内容及示例
程序计数器每个线程一个,当前执行指令地址。比如 System.out.println(...) 执行时,PC 保存当前 JVM 指令的地址。
虚拟机栈(Java栈)每个线程一个,保存方法调用栈帧。方法中的局部变量 user 就保存在此处。
堆(Heap)所有对象实例都在堆中分配,例如 new User(...) 创建的对象。
方法区(元空间)类的结构信息(方法表、常量池、字段表)被加载到这里,如 User.class
本地方法栈调用 Native 方法时使用,例:System.gc() 最终可能调用 native 函数触发 GC

3.垃圾回收
user = null;
System.gc();
上述代码使得 user 不再引用堆中的对象,变成“垃圾对象”。
GC 机制会:
通过可达性分析(引用链)找出不可达对象
标记-清除 / 标记-整理 / 分代收集(Young、Old、Perm)等策略执行清理
如果 User 类中定义了 finalize() 方法,GC 会调用它(只调用一次,不保证执行)

参考文章

最后参考一下细节佬的文章
JVM - JavaEE初阶最后一篇 - 细节狂魔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87177.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87177.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/87177.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

意识边疆保卫战:22:47深圳AI-BioFab人机融合危机全息实录

前言 前些天发现了一个巨牛的人工智能免费学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 &#x1f9e0;《意识边疆保卫战&#xff1a;22&#xff1a;47深圳AI-BioFab人机融合危机全息实录》 副标题&#xff1a;机械义…

langchain从入门到精通(三十四)——RAG优化策略(十)父文档检索器实现拆分和存储平衡

1. 拆分文档与检索的冲突 在 RAG 应用开发中&#xff0c;文档拆分 和 文档检索 通常存在相互冲突的愿望&#xff0c;例如&#xff1a; 我们可能希望拥有小型文档&#xff0c;以便它们的嵌入可以最准确地反映它们的含义&#xff0c;如果太长&#xff0c;嵌入/向量没法记录太多…

Javaweb - 7 xml

XML 是EXtensible Markup Language 的缩写&#xff0c;翻译过来就是可扩展标记语言。即&#xff0c;XML 和 HTML 一样&#xff0c;都是标记语言&#xff0c;也就是说&#xff0c;它们的基本语法都是标签。 特点&#xff1a; 1. 可扩展&#xff1a;即 XML 是允许自定义格式的。但…

qml实现 裁剪进度条

我们需要实现一个垂直进度条效果&#xff0c;但使用图片裁剪的方式。具体需求&#xff1a; 1. 图片位置固定&#xff0c;容器对齐其左边和下边&#xff0c;宽度和图片相同。 2. 容器背景透明&#xff0c;调整裁剪容器的高度&#xff0c;使其有高度进度条的感觉&#xff08;从下…

Dify 工作流全栈解析:从零构建你的 AI 应用流程引擎

AI工作流的导言&#xff1a; 工作流系统&#xff08;Workflow System&#xff09;是 Dify 的核心组成部分&#xff0c;它通过可视化编程界面支持创建复杂的 AI 应用程序。用户可以将不同的功能块连接起来&#xff0c;从而设计出用于处理数据、与 AI 模型交互、管理条件以及执行…

上下位机通讯规则

0&#xff1a;事由 最近开发&#xff0c;上位机Qt与下位机通讯的时候发现通讯规则有些不一样&#xff0c;这里简单记录一下 。所有代码基于元宝生成&#xff0c;属于伪代码不保证真实可用&#xff0c;啊但是逻辑是这么个逻辑。 1&#xff1a;底层通讯规则 以STM32向上位机通讯…

创建平衡二叉树C++

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 平衡二叉树&#xff1a;每个节点的左右子树高度差不超过1 class Solution { public:TreeNode* dfs(vector<int>& nums, int left, int right){if(l…

海光の初体验

背景 八张K100的风扇已经将近一年没转过了…早在今年4月29日&#xff0c;Qwen3正式发布并全部开源8款「混合推理模型」。作为Qwen系列中的最新一代大型语言模型&#xff0c;Qwen3在推理、指令遵循、工具调用、多语言能力等方面进行了全面增强。海光DCU&#xff08;Deep Comput…

场外交易(OTC)财富管理系统开发及解决方案报告

——跨境金融科技赋能机构客户新增长 一、OTC市场现状与机构业务痛点 1. 政策机遇与市场扩容 “北向互换通”期限延长&#xff1a;2025年7月1日&#xff0c;中国外汇交易中心联合香港交易所将利率互换合约期限延长至30年&#xff0c;首日交易规模达15.3亿元&#xff0c;填补超…

pytorch底层原理学习--JIT与torchscript

文章目录 0 目的1 TorchScript1.1 语言特性的限定性1.2 设计目的&#xff1a;模型表达的专注性 2pytorch JIT&#xff08;Just-in-time compilation)2.1pytorch JIT定义2.1pytorch JIT整个过程&#xff1a;1. 前端转换层&#xff1a;生成静态计算图2. 中间表示层&#xff08;IR…

Ubuntu+Nginx+php+SQLite3+typecho手动搭建个人博客

零.Ubuntu环境 一.安装nginx 使用以下指令进行nginx web服务器安装&#xff1a; apt-get install nginx 如果提示找不到安装包&#xff0c;也可以更新一下系统的apt环境包&#xff1a; sudo apt update 安装完成后&#xff0c;可以使用以下指令查看nginx是否处于激活状态&#…

网络协议概念与应用层

1.概念 1.1 例子 点外卖 上述这个过程,就是自定义协议 自定义协议,具体的方式也是非常灵活的 2.几种开发中更常见的格式 2.1xml 上古时期的组织数据的格式 通过标签来组织数据 xml的优势:让数据的可读性变得更好了 劣势:标签写起来繁琐,传输的时候也占用更多网络带宽 2.2…

pytorch学习—7.处理多维特征的输入

2. 线性模型 3.梯度下降算法 4.反向传播(用pytorch算梯度) 5.用pytorch实现线性回归 6.logistic回归 7.处理多维特征的输入_哔哩哔哩_bilibili 7.1代码复现: import numpy as np import torch import matplotlib.pyplot as plt# 1. 获取数据集 xy_data = np.lo

AI助手“智普清言”《三元》(Python)诗解

文本逻辑解清晰&#xff0c;诗意对应技法轻。 笔记模板由python脚本于2025-07-01 06:54:55创建&#xff0c;本篇笔记适合喜欢python三元语句的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Pytho…

本地RAG实战:用Spring AI+Ollama+DeepSeek+ChromaDB增强文档问答

本文手把手教你在本地部署RAG系统&#xff1a; 用 Spring AI 整合 Ollama&#xff08;运行DeepSeek中文模型&#xff09;ChromaDB 存储本地文档&#xff08;PDF/TXT&#xff09;向量Java程序实现&#xff1a;文档解析 → 语义检索 → 增强生成 最终效果&#xff1a;模型回答更准…

Python 数据分析:DataFrame,生成,用字典创建 DataFrame ,键值对数量不一样怎么办?

目录 1 示例代码2 欢迎纠错3 论文写作/Python 学习智能体------以下关于 Markdown 编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右S…

Java 并发编程的 CAS(Compare and Swap)是什么?

CAS&#xff08;Compare and Swap&#xff0c;比较并交换&#xff09; 并非 Java 语言特有的概念&#xff0c;而是现代计算机硬件提供的一条核心原子指令。在 Java 并发编程中&#xff0c;它扮演着“幕后英雄”的角色&#xff0c;是构建高性能、无锁并发工具&#xff08;如原子…

【UnityAssetBundle】AssetBundle打包

AssetBundle生成AB包资源文件方式&#xff1a; Unity编辑器开发&#xff0c;自定义打包工具&#xff1b;官方提供好的打包工具&#xff0c;Asset Bundle Browser 打包 选择一个资源&#xff0c;new一个压缩包名称或选择一个压缩包名称 点击Window->AssetBundle Browser&…

Hush Puppies大中华区鞋类业务移交品牌方继续经营

据悉&#xff0c;随着百丽集团运营的暇步士&#xff08;Hush Puppies&#xff09;大中华区鞋类授权的到期&#xff0c;暇步士&#xff08;Hush Puppies&#xff09;鞋类业务已开始运营权移交。其中线上渠道授权于2025年6月30日正式到期&#xff0c;线下渠道将于2025年12月31日前…

解释LLM怎么预测下一个词语的

解释LLM怎么预测下一个词语的 通过上文词的向量进行映射 在Transformer架构的大语言模型(如GPT系列、BERT等)中,词语会先被转化为词向量。在预测下一个词时,模型会基于之前所有词的向量表示(并非仅仅上一个词,但上一个词的向量是重要信息来源之一)进行计算。 以GPT-2…