「java复用内存」内存复用实现的方式有哪些
本篇文章给大家谈谈java复用内存,以及内存复用实现的方式有哪些对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
怎样用java实现内存动态分配
1、java是如何管理内存的
Java的内存管理就是对象的分配和释放问题。(两部分)
分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。
释放 :对象的释放是由垃圾回收机制决定和执行的,这样做确实简化了程序员的工作。但同时,它也加重了JVM的工作。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。
2、 JVM的内存区域组成
java把内存分两种:一种是栈内存,另一种是堆内存1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;2。堆内存用来存放由new创建的对象和数组以及对象的实例变量 在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理
堆和栈的优缺点
堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。
缺点就是要在运行时动态分配内存,存取速度较慢; 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。
另外,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
1. Java有几种内存?每一种内存有什么功能?哪一种内存速度快?
有六个地方都可以存储数据:
(1) 寄存器(Registers)。这是速度最快的存储场所,因为寄存器其他所有存储媒介都不同:它位于处理器内部。不过,寄存器的数量十分有限,所以寄存器是根据需要由编译器适当地分配。作为一个程序员,我们对此没有直接的控制权,也没办法在程序里头感觉到寄存器的任何存在迹象。
(2) Stack(栈)。位于一般的RAM(random-access memory,随机访问内存)中。处理器通过其指针(“栈指针”,stack pointer)获得处理的直接支持。栈指针若向下(后)移,会分配新的内存;若向上(前)移,则会释放那些内存。这是一种特别快、特别有效率的数据存储方式,速度仅次于寄存器。由于Java编译器有责任产生“将stack指针前后移动”的程序代码,所以它必须能够完全掌握它所编译的程序中“存在stack里头的所有数据的实际大小和存活时间”。如此一来便会限制程序的弹性。由于这个限制,尽管有些Java数据要存储在栈里——特别是对象句柄,但Java对象并不放到其中。
(3) Heap(堆)。Heap是一种通用性质的内存存储空间(也存在于RAM中),用来置放所有Java对象。“内存堆”或“堆”(Heap)胜过stack之处在于,编译器不需知道究竟得从堆里分配多少存储空间,也不需知道从堆上分配的空间究竟要存活多长的时间。因此,用堆存储数据时会得到更大的灵活性。要求创建一个对象时,只需用new即可。执行这些代码时,会在堆里分配空间。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会比从栈里分配花掉更长的时间(假设你真的可以在Java中像C++一样地从stack上产生对象的话)!
(4) 静态存储空间(Static storage)。这儿的“静态”(Static)是指“位于固定位置”(也在RAM里头)。静态存储空间存放着“程序运行期间”一直存在的数据。可用static关键字将某个对象内的特定成员设为静态,但Java对象本身永远都不会置入静态存储空间。
(5) 常量存储空间(Constant storage)。常量值通常被直接置于程序代码里头。因为它们永远都不会改变,所以也是安全的。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(read-only memory,ROM)中。
(6) 非RAM存储空间(Non-RAM storage)。若数据完全存活于程序之外,则程序不运行时数据仍继续存在,脱离了程序的控制范围。其中两个最主要的例子便是“串流化对象(streamed objects)”和“持久性对象(persistent objects)”。在串流化对象形式中,对象会被转换为一连串的字节(bytes)流,这些bytes通常会被传送给另一台机器。而在持久性对象形式中,对象被存储于磁盘,即使程序运行结束,这些对象还能够继续保有。这种类型的存储空间的特点在于,它们能够将对象转换为可存储于其他媒介的形式,并在需要时,将所存储的数据还原成可存储于RAM中的一般对象。Java提供了对“轻量级持久性(Lightweight persistence)”的支持。新版本有可能提供更完善的解决方案。
针对你的补充我也补充一下:堆内存和栈内存确实是我们常常用的东西,比如
Animal a = new Animal();
这个时候相当于在堆内存中开辟了一个空间保存了Animal的信息以及着块空间的内存地址,然后在栈内存中划了一小快空间保存了堆中的内存地址,这个时候我们就可以说引用a指向Animal()了.
可是有时候,有个静态类.Animal,里面有个静态方法speak();
那么可以这么直接调用Animal.sepak();
这个时候既没有new,也没有Animal a=??;
所以既没有在堆中开辟空间也没有在栈内存中开辟空间 ,
可是方法确实能执行,一切程序都运行在内存里,那么证明有新的内存区,就是静态空间了.
当然还有常量什么的等等
Java 变量是否共用内存的问题
首先,回答你的第一问。一个类,如果有成员域,没有针对于每个成员写set()方法的时候,那么,如果该成员为简单数据类型,改变成员的方法,就是重新赋值。如果成员都为引用,那么,改变成员的原理就是使这个引用指向另一块堆内存,这也就相当于String类型的引用,要改变这个引用,就是使这个引用指向另一个对象,原理是一样。
p1,p2指向同一块类存的时候,修改p1,是不会影响p2的,因为p1,知识个引用,如果你修改那块内存中的数据的话,那么对p1,p2都会有影响。打个比方吧,如果两个小朋友都要去学校,这两个小朋友就是p1,p2,学校就相当于是那一块内存。现在你要修改p1,也就是类似于,p1这个小朋友不去学校了,要去超市了,而p1要去哪里,不会影响p2去学校。而,如果你把学校内容给换了,在学校里面开商店,把学校改装成了超市,那么,两个小朋友p1,p2还以为学校没有变,结果,都往学校去了,到了学校一看,才知道他们去了超市。
你这个例子,有点特殊,设计的内容不是一点点。我尽量细得给你讲讲吧。
Integer p1 = a;这种赋值方法,从JDK1.5以后出现的新特性,在这之前给包装类赋值的方法都是 Integer p1 = new Integer(a);而jdk1.5后出现了自动装箱的功能,将一个基本数据类型包装成一个包装类,并且包装类能够进行和基本数据类型进行直接计算,如 Integer x = 4; x = x+3; 这里第二句运算的原理,牵涉到一个包装类自动拆箱的原理,在JVM中,实际上是调用了 x.intvalue()这个方法。注意这里x不能为空,因为x为null是合法的,但是一旦为null就不能直接和数值进行计算。
现在解释一下,为什么a在[-128,127]之间,p1==p2为true,而超出这个范围就是false:[-128,127]是byte的范围,而这个范围的数值是一直存在内存中的,所以,在建立新对象的时候,发现内存中有数据,则直接让该包装类引用指向这块类存,所以,在建立p1,p2的时候,发现类存中有a这个值,所以,p1,p2都指向这同一块内存。而当数值超出这个范围的时候,就重新开辟空间,不管之前是否有对象有这个值,都会开辟新的空间,所以,超出这个范围,p1==p2就为false了,因为他们指向的内存地址不同。
花了半小时组织语言给你解答,希望采纳哈~~ 如果有不懂得,再追问!
Java 的内存管理机制是怎样的?
Java的内存分配有三种, \x0d\x0a1、静态存储区:内存在程序编译时就分配好了,比如静态变量; \x0d\x0a2、栈区:各种原始数据类型的局部变量都是在栈上创建的,当程序退出该变量的作用范围的时候,这个变量的内存会被自动释放。 \x0d\x0a3、堆区:对象(包括数组)都是在堆中创建的。程序在运行的时候用new关键字来创建对象,对象创建时会在堆中为其分配内存。
java复用内存的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于内存复用实现的方式有哪些、java复用内存的信息别忘了在本站进行查找喔。