非静态类ClassA中有一个static方法A1,非静态类ClassB中有一个非static方法B1,public class ClassA
{
  public static A1()
  {
    ClassB b=new ClassB();
    b.B1();
  }
}问题如下:
1、不调用ClaaA.A1()之前,A1是否占用了内存?
2、调用到ClaaA.A1()后,A1是否占用了内存?
3、如果占用了内存,什么情况下回收内存,是不是在程序结束时,才回收内存?

解决方案 »

  1.   

    问题补充:
    4、调用后A1()后的,A1中的ClassB被实例化,b什么情况下回收内存?
      

  2.   


    lz其实没有说变量——或者对象,是说的A1方法。呵呵!
      

  3.   

    A1() 是个方法,在执行过程中 会 实例化一个 B类,即在执行的时候内存中会多一个B的实例,在不执行该方法时即不会新建任何对象,当然也不会占用内存,托管对象的内存管理机制你可以看看相关资料,但是程序结束时一定会翻放。
      

  4.   


    程序结束,是指整个程序结束,还是指一部分?什么情况下程序才会结束呢?如果不重启IIS,有什么方法可以让程序结束不?
      

  5.   

    我的理解是这样的:不管什么类型的方法在被调用之前都不占内存...有调用才会开始使用内存,方法结束后便释放该方法里的资源(GC回收)static方法执行起来会比非static的方法快一些,非static的方法浪费掉的时间是等待类别的实体化
      

  6.   


    当闭当前进程。。IIS如果不重启你可以针对某个网站停止然后再启动,如果配置了应用程序池的,可以直接回收应用程序池,或者结束w3wp.exe
      

  7.   

    方法肯定是要占用内存的,方法占用内存的是字节码,只有dll会动态装入,如果在exe中的方法,肯定在运行exe的时候就把所有方法都装入内存,不论是static还是普通的方法,
      

  8.   

    呵呵,在.net使用到一个类的时候,一定会把它调入内存的(而且还会Jit编译)。至于说何时调入代码,何时清除掉编译后的缓存,那是.net底层自己的事情了。如果你在意这个,那么就写一个测试。我关心的是你如何测试。例如你担心他会让你的程序没有内存可用,那么你就实际去让自己的程序尽量去使用内存,看看到底是否自己的程序可以分配到内存。如果可以分配,那么它占用内存对于你来说就没有什么妨害的。以测试为基准,如果我们只知道担心什么,却不知道要如何测试出来这种担心、无法用程序来让它演示出来,那么我们的担心十有八九就是多余的。
      

  9.   


    实例类型,实例化之后,就已经占用内存了。
    但是实例化,内存不会分配空间给你实例化的对象。
    静态变量,比如 static int x =3,在编译的时候,x 这个变量名会被编译到 pe文件里去,运行的时候,通过文件偏移和内存偏移,相对映射,也就是说,编译的时候变量x已经以一个基址+内存偏移的方式存储了。但是静态变量开始初始化之前,地址是相对固定了,但是地址里面的值是无意义,也就是调用之前是存储的0。当你程序有方法第一次要调用的时候,需要调用该静态变量的时候,就初始化了,该变量就会一直存在内存中(这个有变量值个变量地址的概念)但是这个初始化的过程是在运行时的,其实早在编译时,你的静态方法和变量,已经有一个固定的偏移地址,只是没有值而已。这就是为什么实例方法,变量可以调用静态方法和变量的原因。
    但是实力方法和变量,他的内存分配是在运行时的,所以地址无法固定,其实就是内存的偏移的固定,也就是说变量地址是动态的。所以同理,实例方法无法调用静态方法和静态变量的原因。
    这个不得不说下常量,常量大家都知道定义的时候是必须赋值的,因为常量不是变量,不能再运行时去修改它,所以常量在编译时已经把上面提到的内存偏移地址和固定的具体存储的值也已经固定了。
    其实楼主有兴趣去了解下,汇编里面函数调用如果利用堆栈平衡的,和PE文件格式。C里面的指针的概念,很多东西就可以帮助你去理解,以上的概念,我也是根据对这套知识理解,然后总结出来的。并一定正确,经供参考,估计八九不离十。有时间深入研究下.net pe的元数据才能给出更准确的答案。
      

  10.   


    打错了很多字,从新来过实例类型,实例化之后,就已经占用内存了。
    但是在类实例化之前,内存不会分配空间给你实例化的对象。
    静态变量,比如 static int x =3,在编译的时候,x 这个变量名会被编译到 pe文件里去,运行的时候,通过文件偏移和内存偏移,相对映射,也就是说,编译的时候变量x已经以一个基址+内存偏移的方式存储了。但是静态变量开始初始化之前,地址是相对固定了,但是地址里面的值是无意义,也就是调用之前是存储的0。当你程序有方法第一次要调用的时候,需要调用该静态变量的时候,就初始化了,该变量就会一直存在内存中(这个有变量值个变量地址的概念)但是这个初始化的过程是在运行时的,其实早在编译时,你的静态方法和变量,已经有一个固定的偏移地址,只是没有值而已。这就是为什么实例方法可以调用静态方法和变量的原因。但是实力方法和变量,他的内存分配是在运行时的,所以地址无法固定,其实就是内存的偏移的固定,也就是说变量地址是动态的。所以同理,静态方法无法调用实例方法和变量的原因。这个不得不说下常量,常量大家都知道定义的时候是必须赋值的,因为常量不是变量,他是在编译时就固定了。不能再运行时去修改它,所以常量在编译时已经把上面提到的内存偏移地址和固定的具体存储的值也已经固定了。其实楼主有兴趣去了解下,汇编里面函数调用如果利用堆栈平衡的,和PE文件格式。C里面的指针的概念,很多东西就可以帮助你去理解,以上的概念,我也是根据对这套知识理解,然后总结出来的。并一定正确,经供参考,估计八九不离十。有时间深入研究下.net pe的元数据才能给出更准确的答案。
      

  11.   

    方法 (Method) 是一种类型定义,所以,它被存放在 Type Object 上,Type Object 是一个被分配在托管堆上的特殊类型,在同一个 AppDomain 中,每一个类型,都对应一个全局的 Type Object。每个引用类型的实例,都包含一个指向它的直接类型的 Type Object 的指针,每个 Type Object 也存在类似的指针,用来标识它的直接父类型的 Type Object。当调用静态方法时,CLR 会根据方法调用去寻找其对应的 Type Object,然后,把方法 JIT,JIT 之后的方法是本机代码,可以直接运行,然后,这部分代码被加载进入内存,方法的参数被加载进入当前执行栈,原来的执行上下文地址也被记录到执行栈;方法开始执行,执行完后,执行栈中的返回地址被读出,然后 CLR 利用本机跳转指令,跳转到该返回至继续执行。当调用实例方法时,CLR 会根据实例的 Type Object 指针找到对应的 Type Object,然后,把方法 JIT,JIT 之后的方法是本机代码,可以直接运行,然后,这部分代码被加载进入内存,该实例对象,以及方法的参数被加载进入当前执行栈 (实例对象永远是第一个参数,即 arg0,利用 ldarg0 指令进行读取),原来的执行上下文地址也被记录到执行栈;方法开始执行,执行完后,执行栈中的返回地址被读出,然后 CLR 利用本机跳转指令,跳转到该返回至继续执行。如果方法已经被 JIT 过,则不会被第二次 JIT。方法在 IL 中是以字节流的形式存在的,所以,它仍然会占据内存。方法 JIT 之后会被驻留在该进程的地址空间里面,因此,它也会在运行时占据内存。方法的元数据存放在程序集 MethodRef 以及 MethodDef 表中。 总结下,不管是实例还是静态方法,被JIT只存在一份,不过实例方法多了一个引用该实例的参数作为它的第一个参数!