JVM(二)

Java类加载机制详解

什么是类加载

把类的.class文件中的二进制读入(加载)到内存中

类加载目的是什么

在堆中的方法区里面存储.class对象,把类的信息结构存到堆里面 , 首先说明方法区是在堆里面

类加载的信息存储到了那?

在这里插入图片描述

类加载是如何加载的?

类加载有两种形式,一种是jvm的,另一种是用户自定义的, jvm有3中, 用户自定义的只需要继承了classLoader就可以.

根加载器Bootstrap

根加载是jvm核心加载器,他是由C++来写的, 对于java.lang里的所有类都是属于跟加载器
他没有继承ClassLoader

扩展加载器Extension

他的父加载器是Bootstrap
继承了ClassLoader
一般加载的是系统属性或者jdk加载

系统类加载器 System

父加载器是扩展加载器Extension
继承了ClassLoader
根据classpath进行加载
自定义加载器属于系统类加载器

用户自定义加载器

如果用户想自定义加载器那么首先是继承ClassLoader,他的默认加载器属于是系统类加载器

加载的流程

加载流程跟继承父子类初始化非常的相似, 加载的时候首先加载的是父类,然后加载子类
如果父类加载成功. 父类认为是定义类, 包括父类以下都属于初始化类
为什么这样做,首先加载父类?
如果先加载的父类,那么我们的父类会约束我们的自定义 加载器,防止出现不安全的类被加载

举一个例子

在根加载器里面我们 有一个object类, 假如父加载器没有约束我们,那么这个时候我们自定义加载器来冒充object类,所以不安全, 假如我们可以根加载器可以约束, 那么他就不会被冒充,她会去父加载里面加载,避免了冒充

类对象什么时候被卸载了?

通过图我们可以看出当类对象没有系统类型加载器引用,也没有实例对象引用的时候,那么这个时候他就已经被卸载了
在这里插入图片描述

需要注意的是根加载器Bootstrap是不可能被卸载的,因为他会一直引用类对象, 所以类对象不会被卸载

什么是连接

类加载完成之后就是连接, 连接分为3个阶段

验证

验证主要是查看代码是否规范
文件架构检查

准备

静态变量分配内存
赋初始值
下面有代码

解析

1 把类符号引用转换为直接引用

Car.run 在二进制里面run就是一个类字符, 但是解析的时候就变成了直接引用,也就是指针

初始化

也就是为静态变量赋值

方法区里面存储了什么

类信息, 常量, 静态变量, 常量池,编译后的代码

在以前的是产量池是单独管理的,使用了和堆一样的gc回收,但是由于bug或者效果不收,所以没有使用,老年代的时候

代码介绍 ClassLoader

通过下面代码我们引入话题.

这段代码运行出的结果是什么?

   public class Test3 {
    public static void main(String[] args){
        t  test3 = t.getTest();
        System.out.println(test3.anInt);
        System.out.println(test3.anInt1);

    }
}
   class t {
        public static int anInt ;
        public static int anInt1 = 0;
       private static t test = new t();

        private t() {
            anInt++;
            anInt1++;
        }

        public static t getTest(){
            return test;
        }

}


1
1

如果是这样的,那么运行结果是什么样子的呢?

 class t {
        private static t test = new t();
        public static int anInt ;
        public static int anInt1 = 0;
    

        private t() {
            anInt++;
            anInt1++;
        }

        public static t getTest(){
            return test;
        }

1
0

为什么会出现这种情况呢?跟什么有关系

  1. 跟类加载器有关
  2. 程序执行顺序有关

编译常量

public class ClassLoaderTest2 {
 public static void main(String[] args){
     System.out.println(FinalTest2.x);

 }
}
class FinalTest2{
    public static final int x=18/3;
    static {
        System.out.println("this is judy");
    }
}

运行结果: 6 this is judy

public class ClassLoaderTest3 {
    public static void main(String[] args){
        System.out.println(FinalTest3.x);
    }
}
class FinalTest3{
    public static final int x= new Random().nextInt(100);
    static {
        System.out.println("this is judy");
    }
}

运行结果: this is judy 6

为什么会出现这种问题?

第二种方式的时候发现类被初始化了,他已经不属于编译时的常量了, 而第一种情况看是在编译的时候已经初始化赋值了,所以先执行的6后执行的this is judy

初始化

class Parent{
    static  int a=3;
    static {
        System.out.println("Parent2 static block");
    }
}

//父类已经被初始化过,所以不会再次被初始化
class Child extends Parent{
    static int b=4;
    static {
        System.out.println("child static block");
    }

}

public class ClassLoaderTest4 {
    static {
        System.out.println("Test5 static block");
    }
    public static void main(String[] args){
        //不是创建类的实例,不是主动使用
        Parent parent;
        System.out.println("--------------------------");
        parent = new Parent();
        System.out.println(Parent.a);
        System.out.println(Child.b);
    }
}

运行结果:
Test5 static block
#--------------------------
Parent2 static block
3
child static block
4

**项目名称:** 基于Vue.js与Spring Cloud架构的博客系统设计与开发——微服务分布式应用实践 **项目概述:** 本项目为计算机科学与技术专业本科毕业设计成果,旨在设计并实现一个采用前后端分离架构的现代化博客平台。系统前端基于Vue.js框架构建,提供响应式用户界面;后端采用Spring Cloud微服务架构,通过服务拆分、注册发现、配置中心及网关路由等技术,构建高可用、易扩展的分布式应用体系。项目重点探讨微服务模式下的系统设计、服务治理、数据一致性及部署运维等关键问题,体现了分布式系统在Web应用中的实践价值。 **技术架构:** 1. **前端技术栈:** Vue.js 2.x、Vue Router、Vuex、Element UI、Axios 2. **后端技术栈:** Spring Boot 2.x、Spring Cloud (Eureka/Nacos、Feign/OpenFeign、Ribbon、Hystrix、Zuul/Gateway、Config) 3. **数据存储:** MySQL 8.0(主数据存储)、Redis(缓存与会话管理) 4. **服务通信:** RESTful API、消息队列(可选RabbitMQ/Kafka) 5. **部署与运维:** Docker容器化、Jenkins持续集成、Nginx负载均衡 **核心功能模块:** - 用户管理:注册登录、权限控制、个人中心 - 文章管理:富文本编辑、分类标签、发布审核、评论互动 - 内容展示:首页推荐、分类检索、全文搜索、热门排行 - 系统管理:后台仪表盘、用户与内容监控、日志审计 - 微服务治理:服务健康检测、动态配置更新、熔断降级策略 **设计特点:** 1. **架构解耦:** 前后端完全分离,通过API网关统一接入,支持独立开发与部署。 2. **服务拆分:** 按业务域划分为用户服务、文章服务、评论服务、文件服务等独立微服务。 3. **高可用设计:** 采用服务注册发现机制,配合负载均衡与熔断器,提升系统容错能力。 4. **可扩展性:** 模块化设计支持横向扩展,配置中心实现运行时动态调整。 **项目成果:** 完成了一个具备完整博客功能、具备微服务典型特征的分布式系统原型,通过容器化部署验证了多服务协同运行的可行性,为云原生应用开发提供了实践参考。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think>嗯,用户问的是Redis作为一级缓存,JVM作为级缓存的介绍。首先,我需要确定这两个概念在缓存系统中的作用和位置。通常,一级缓存(L1)是离应用最近的,速度最快,但容量较小;级缓存(L2)则更大但稍慢一些。不过这里用户提到的是一级用Redis,级用JVM,这似乎和常见的JVM一级、Redis级的结构相反,可能用户有特殊需求或者配置,我需要先确认这点是否正确。 接下来,我需要解释这两个缓存的角色。Redis作为内存数据库,通常作为分布式缓存使用,适合做级缓存,而JVM缓存如Ehcache或Caffeine作为一级,因为它们在应用进程内,访问更快。但用户的情况反过来,可能需要说明这种架构的适用场景,比如可能考虑到网络延迟或其他因素,将Redis作为更接近数据源的一级,而JVM作为级补充? 然后要分析两者的优缺点。Redis作为一级,优点是分布式、一致性好,但网络延迟可能影响速度。JVM作为级,访问速度快,但容量有限,数据不一致风险。需要比较两者的读写策略,比如如何保持同步,常见的策略如写穿透、写回等。 还要考虑数据同步机制,比如如何确保Redis和JVM缓存的一致性,可能使用消息队列或者发布订阅机制来通知缓存失效。此外,适用场景方面,这种架构可能用于需要快速访问但又能容忍一定程度数据延迟的应用,或者作为多级缓存的优化策略。 需要注意用户可能的混淆,是否将一级和级的顺序搞反了,但按照问题描述,还是按用户说的来回答。同时,检查是否有误,比如Redis作为一级是否合理,或者是否有其他考虑因素,比如网络架构使得Redis更接近应用,成为一级缓存。 最后,总结这种架构的优缺点和使用场景,帮助用户理解何时选择这样的方案,以及需要注意的问题,比如数据一致性、缓存击穿、雪崩等常见问题,以及如何通过TTL、熔断机制等来缓解。</think>好的,我将分步骤为您解释“Redis一级缓存 + JVM级缓存”的架构设计及其工作原理: 1. **基础概念** - **一级缓存(Redis)**:位于应用层外部,基于分布式内存数据库的缓存,所有服务实例共享同一份缓存数据。 - **级缓存(JVM)**:位于应用进程内部(如堆内存),通过HashMap、Ehcache、Caffeine等实现,仅当前实例可见。 2. **数据访问流程** ``` 请求 → 检查JVM缓存 → 命中则返回 ↓ 未命中 检查Redis缓存 → 命中则返回并写入JVM ↓ 未命中 查询数据库 → 写入Redis → 写入JVM → 返回 ``` 3. **核心优势对比** | 特性 | Redis一级缓存 | JVM级缓存 | |---------------|----------------------------------|----------------------------| | 数据一致性 | 全局一致 | 单机一致,集群可能不一致 | | 访问速度 | 微秒级(网络IO开销) | 纳秒级(内存直接访问) | | 容量 | 十GB~百GB级 | MB~GB级(受堆内存限制) | | 数据共享 | 跨进程、跨机器共享 | 仅进程内有效 | 4. **同步策略设计** - **写操作处理**: ```java public void updateData(Data newData) { // 先更新数据库 db.update(newData); // 删除两级缓存(保证后续读取加载最新值) redis.delete(key); localCache.invalidate(key); } ``` - **过期控制**: - Redis设置TTL(如30分钟) - JVM设置更短的TTL(如10分钟)避免长期脏数据 5. **性能优化技巧** - **JVM缓存预热**:服务启动时批量加载热点数据 - **Redis布隆过滤器**:防止缓存穿透 - **分级TTL策略**: $$ TTL_{JVM} = \alpha \cdot TTL_{Redis} \quad (0 < \alpha < 1) $$ - 异步刷新:后台线程主动更新临近过期的热点数据 6. **典型应用场景** - 高并发读(>10k QPS)且数据变更频率较低的场景 - 电商商品详情页 - 新闻类内容展示 - 地理位置信息查询 7. **风险控制措施** - **熔断机制**:Redis故障时自动降级为纯JVM缓存 - **限流策略**:使用令牌桶控制数据库访问量 - **监控指标**: ```mermaid graph TD A[缓存命中率] --> B(Redis命中率>85%) A --> C(JVM命中率>95%) D[延迟分布] --> E(Redis P99<2ms) D --> F(JVM P99<100μs) ``` 8. **数据一致性保障** - 最终一致性模型: 1. 数据库更新成功后 2. 通过Redis Pub/Sub广播失效指令 3. 各节点监听通道并清除本地JVM缓存 $$ \text{不一致时间窗口} \leq T_{pub/sub} + T_{network} $$ 这种多级缓存架构需要根据业务特征进行参数调优,建议通过压力测试确定最佳TTL值和缓存容量比例。当数据更新频繁(如库存秒杀场景)时,需谨慎评估使用此模式。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王雪芬-ghqr-264962

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值