堆内存

Java中堆内存和栈内存详解

ぐ巨炮叔叔 提交于 2020-03-08 12:58:49
  Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。   在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。 当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。   堆内存用于存放由new创建的对象和数组。 在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。    引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放 。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放, 数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉 。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针! java中内存分配策略及堆和栈的比较    1

JVM内存管理基本知识

不问归期 提交于 2020-03-08 04:30:34
这篇本来是想好好写的,今天看了一天了的,可是,组会好像有种要悲剧的感觉啊。。暴风雨前的宁静,尽量记录一些吧。 上周把爬虫代码优化后,就哈皮哈皮的和未优化的版本一起跑了。起初,由于未优化的版本已经run了几天了,内存占用在200M多,而发现优化后的内存占用只有40M,所以很开心。但是不久就发现,优化后的版本,内存占用也会慢慢增加,大有一种“老娘给你分多少,你就要用多少”的赶脚。 用jprofiler监控,自己开发的类的对象数量都比较正常,所以决定学习一下JVM内存管理相关的东西。 JVM主要管理两种类型的内存:堆(Heap)和非堆。 按照官方的说法:“Java虚拟机具有一个堆, 堆 是 运行时 数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。” “在JVM中堆之外的内存称为 非堆 内存(Non-heap memory)”。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。 堆内存分配 JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到

C++之指针、引用、数组、堆区栈区

此生再无相见时 提交于 2020-03-07 12:41:28
指针 指针(pointer)是一个值为内存地址的变量(或数据对象) 基本用法 数据类型 * 指针变量名 如 int * ptr_num 注意: Int* p 写法偏向地址 P是一个地址变量 表示一个十六进制地址 Int *p偏向值 *p是一个整型变量 能够表示一个整型值 给指针赋值只能使用&符号 空指针(null pointer)空指针不指向任何对象,在试图使用一个指针之前首先检查是否为空 Int *ptr1 = nullptr; 如果用null需要包含cstdlib Void 指针 一种特殊的指针类型 可以存放任意对象的地址 注意: void 指针存放一个内存地址,地址指向的内容是什么类1、型不能确定 2、Void 类型指针一般用来:拿来和别的指针比较,作为函数的输入和输出;赋值给另一个void 指针 指针小结: 指针同样是一个变量,只不过该变量中存储的是另一个对象的内存地址 如果一个变量存储另一个对象 的地址,则称该变量指向这个对象 指针变量可以赋值 指针的指向在程序执行中可以改变 指针P在执行中某时刻指向变量x在另一时刻可以指向y 注意: 指针命名规则和其他变量命名规则一样 指针不能与现有变量重名 应为指针指定一个地址后才能在语句中使用指针 引用 为对象起了另外一个名字(引用即别名) Int int_value = 1024; //refValue指向int_value

Java内存划分--数组内存图

我是研究僧i 提交于 2020-03-07 03:28:44
Java内存划分 5 一,栈: 存放的都是方法中的 局部变量,方法的运行一定要在栈当中。 局部变量:方法的参数,方法{}中的变量 作用域:一旦超出作用域,立刻从栈内存中消失。 二,堆: 凡是 new 出来的东西,都在堆当中 堆内存里面的东西都有一个地址值:16进制 堆里面的数据都有默认值: ​ 整数 默认为0 ​ 浮点数 默认为0.0 ​ 字符 默认为 ‘\u0000’ ​ 布尔 默认为false ​ 引用类型 默认为null 三,方法区: 存储 .class 相关信息,包含方法的信息 四,本地方法栈 与操作系统相关 五,寄存器: 与 cpu 相关 一个数组的内存图 方法信息 存储在 方法区中 运行方法就必须将 方法信息 加载到栈中,并在栈中开辟空间,存储数组名 new的时候 是在堆里面,在堆中开辟一段内存空间,编号,赋予16进制地址值。 将地址值赋给栈里面的数组名。 根据索引赋值的时候,通过数组名的地址,在堆中找到相应内存地址,按照索引递增,找到相应地址 两个数组的内存图 类比一个数组,我都懒得写了… 还是要注意压栈的问题 画这个图,实际上是为下面做铺垫 两个引用指向同一个数组 其实图里面已经可以很清楚的看到,虽然 B数组是被 A数组赋值了,但是,B数组依然能够指向内存中new出来的数组地址, 由此,不难看出,通过 数组B 一样能够改变 堆内存中的数组 实际上,是堆内存共享了

JVM源码分析之不可控的堆外内存

我怕爱的太早我们不能终老 提交于 2020-03-05 13:27:10
概述 之前写过篇文章,关于堆外内存的, JVM源码分析之堆外内存完全解读 ,里面重点讲了DirectByteBuffer的原理,但是今天碰到一个比较奇怪的问题,在设置了-XX:MaxDirectMemorySize=1G的前提下,然后统计所有DirectByteBuffer对象后面占用的内存达到了7G,远远超出阈值,这个问题很诡异,于是好好查了下原因,虽然最终发现是我们统计的问题,但是期间发现的其他一些问题还是值得分享一下的。 不得不提的DirectByteBuffer构造函数 打开DirectByteBuffer这个类,我们会发现有5个构造函数 DirectByteBuffer(int cap); DirectByteBuffer(long addr, int cap, Object ob); private DirectByteBuffer(long addr, int cap); protected DirectByteBuffer(int cap, long addr,FileDescriptor fd,Runnable unmapper); DirectByteBuffer(DirectBuffer db, int mark, int pos, int lim, int cap,int off) 我们从java层面创建DirectByteBuffer对象

托管堆和垃圾回收(GC)

自闭症网瘾萝莉.ら 提交于 2020-03-05 01:20:24
一、基础 首先,为了深入了解垃圾回收(GC),我们要了解一些基础知识: CLR :Common Language Runtime,即公共语言运行时,是一个可由多种面向CLR的编程语言使用的“运行时”,包括内存管理、程序集加载、安全性、异常处理和线程同步等核心功能。 托管进程中的两种内存堆: 托管堆 :CLR维护的用于管理引用类型对象的堆,在进程初始化时,由CLR划出一个地址空间区域作为托管堆。当区域被非垃圾对象填满后,CLR会分配更多的区域,直到整个进程地址空间(受进程的虚拟地址空间限制,32位进程最多分配1.5GB,而64位最多可分配8TB)被填满。 本机堆 :由名为VirtualAlloc的Windows API分配的,用于非托管代码所需的内存。 NextObjPtr :CLR维护的一个指针,指向下一个对象在堆中的分配位置。初始为地址空间区域的基地址。 CLR将对象分为大对象和小对象,两者分配的地址空间区域不同。我们下方的讲解更关注小对象。 大对象 :大于等于85000字节的对象。“85000”并非常数,未来可能会更改。 小对象 :小于85000字节 的对象。 然后明确几个前提: CLR要求所有引用类型对象都从托管堆分配。 C#是运行于CLR之上的。 C# new 一个新对象时,CLR会执行以下操作: 计算类型的字段(包括从基类继承的字段)所需的字节数。

堆溢出 Heap Corruption

可紊 提交于 2020-03-02 08:14:22
http://chinamars.me/blog/2014/01/heap-corruption-堆溢出/ 申明:本文并非原创,参考了许多大牛的文章,因为太乱了所以没有标明出处,如有侵犯版权问题,请第一时间联系我。 No copyright infringement intended,If so,please contact me immediately. 0x01 背景知识 堆是程序运行时动态分配给程序的内存空间,堆内存空间发生缓冲区溢出很常见。堆溢出需要不同的手段,不像栈溢出那么简单。 分配给一个函数的内存会持续保持分配直到完全被释放为止,所以被溢出的内存使用时才会被发现。堆的结构如下图。 0x02 使用堆 堆内存一般通过malloc()分配, malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。通过free()释放。 PS:在不同的系统之间,对堆管理的实现没有一个统一标准,甚至在UNIX系统中也使用了几个不同的标准。 下面的例子演示了简单的堆溢出。 #include <stdio.h> int main(int argc,char* argv){ char *A= malloc(10); char *B= malloc(8); char *C= malloc(4); strcpy(B,"BBBBBBBB"); strcpy(C,

扩展堆数组的大小

我与影子孤独终老i 提交于 2020-03-01 20:54:59
函数: void* realloc(void *ptr, size_t size); 功能: 函数将 ptr 对象的储存空间改变为给定的大小 size 。 参数 size 可以是任意大小,大于或小于原尺寸都可以。 返回值是指向新空间的指针,如果错误发生返回NULL。 扩展内存 1 int main() 2 { 3 const size_t pSize = 15; 4 5 char *p = new char[pSize]{0}; 6 strcpy_s(p, pSize, "I LOVE YOU"); 7 8 cout << "p:" << hex << (int)p << endl; 9 10 p = (char *)realloc(p, pSize * 2); 12 13 if (!p) 14 cerr << "Call realloc function error!" << endl; 15 16 17 cout << "p1:" << hex << (int)p << endl; 18 _snprintf_s(p, pSize * 2, pSize * 2, "Hello,%s C++!", p); 19 cout << p<< endl; 20 21 delete[]p; 22 23 getchar(); 24 return 0; 25 } 如果没有 p = (char *

jvm内存设置

匆匆过客 提交于 2020-03-01 06:57:17
Eclipse崩溃,错误提示: MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) space remains. It is strongly recommendedthat you exit and restart MyEclipse with new virtual machine memoryparamters to increase this memory. Failure to do so can result indata loss. The recommended Eclipse memory parameters are: eclipse.exe -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M 1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了-Xms128m JVM初始分配的堆内存-Xmx512m JVM最大允许分配的堆内存,按需分配-XX:PermSize=64M JVM初始分配的非堆内存-XX

C中堆管理—浅谈malloc,free,calloc,realloc函数之间的区别

拥有回忆 提交于 2020-03-01 03:05:02
在进行C/C++编程的时候,需要程序员对内存的了解比较好清楚,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般由程序员分配与释放,基程序员不释放,程序结束时可能由操作系统回收(C/C++没有此等回收机制,Java/C#有),注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 全局区(静态区)(static):全局变量和静态变量的存储是放在一块儿的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。 文字常量区:常量字符串是放在这里的,程序结束后由系统释放。 程序代码区:存放函数体的二进制代码。 C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h。它们的声明如下: void * malloc(int n); void free (void * p); void *calloc(int n,int size); void * realloc(void * p,int n); 1. malloc函数 malloc函数可以从堆上获得指定字节的内存空间