【JVM】spring单例内存管理简单分析

本文探讨了Spring框架中单例bean的内存管理与设计模式中单例的区别。Spring通过DefaultSingletonBeanRegistry管理bean实例,保存在ConcurrentHashMap中。控制器类如HelloController的实例和成员变量内存分布不同:静态变量如logger存储在方法区,非静态变量如view存储在堆中。Spring的单例对象生命周期与容器同步,成员变量是否static不影响使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【JVM】spring单例内存管理简单分析

问题描述:
spring框架中controller类实例为单例
开发过程中,在controller中定义的成员变量是否添加 static 描述符,在内存管理上会有区别吗?

设计模式中单例的一个例子:

public class Singleton {
    private static Singleton sing = new Singleton();
   
    private Singleton() {}
    public static Singleton getInstance() {
        return sing ;
    }
    
}
设计模式里的单例内存管理情况如下:
Singleton的类信息会保存在方法区内,包括类名,类属性等
 private static Singleton sing  这个静态变量也保存在方法区
new Singleton();  生成的对象实例保存在堆中
在堆中会创建Singleton类的Class实例作为该类信息的引用入口

比如在一个方法中有这样的语句:Singleton a = Singleton.getInstance();
getInstance() 通过这个方法所获得的是指向堆中保存的已经存在的实例的引用
Singleton a 这个变量保存在当前线程的局部变量表中,属于线程私有的 

设计模式中的单例,需要程序员显示的在堆中分配内存保存该实例


在spring中的singleton与设计模式的singleton有所差别
spring是针对一个IOC容器维持一个bean实例
而设计模式则是对一个classloader所载入的类的一个实例

在spring中,controller实例为单例,即在spring IOC中只维护了一个controller实例
具体实现是,在IOC容器中通过 DefaultSingletonBeanRegistry类 来管理的
其中关联的数据结构为:
/** Cache of singleton objects: bean name --> bean instance */
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();

一个controller 类定义:
public class HelloController implements Controller{
   
    private String view;
    private static Logger logger = Logger.getLogger(HelloController.class.getName());
     //private Logger logger = Logger.getLogger(HelloController.class.getName());

    @Override
    public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1)
            throws Exception {
        logger.info("handleRequest " + this.getClass().getName());
        String hi = arg0.getParameter( "test");
        //throw new IOException();
        return new ModelAndView(view, "test", hi);
    }
   
    public void setView(String view) {
        this.view = view;
    }
}
该controller 类的内存管理如下:
描述 HelloController 的类信息保存在方法区
描述 view 变量的信息保存在运行时常量区
描述 logger 变量的信息及其引用值保存在方法区
同样在堆中也会创建该controller类的Class实例

在spring中,我们不需要直接的 new 的操作去创建controller的实例
程序执行过程会由IOC容器分配内存保存controller实例并进行维护
这个controller实例保存在一个Map中,这个Map也是在堆中进行维护的
同时controller实例对象的引用的维护也不需要我们来考虑,spring框架会为我们进行处理

回到最初的问题,在HelloController中,定义了static变量 logger 
logger 变量 和 view 变量之间的差别是什么?
明显差别是两者保存的地方是不同的
对于view变量,由于其为对象成员变量,因此会与实例对象保存在堆中
而logger为static,则会保存在方法区中,且只有一份实例

在实际执行的过程中,由于spring所维护的controller为单例
即对于spring程序上下文来说,只存在一份controller实例
不同线程获取该实例进行处理时,实际上是对同一份内存区域进行处理

而spring 的生命周期与程序的生命周期对应,因此spring IOC所维护的各个对象实例的生命周期也与程序一样

因此造成controller的单例对象及其内的成员变量也具有伪“static”的属性
在内存中仅有一份,这里的一份是对于当前spring IOC容器来说

也就是说spring所维护的单例对象是堆中的对象,且该对象在spring IOC容器存活过程中都会存在
对于对象内的成员变量,是否声明为static,对于变量的使用并没有影响
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值