package com.jvmfinalstatic;
//需求分析:本节学习java虚拟机的内存方面问题
//参考文献:http://blog.youkuaiyun.com/yangyuankp/article/details/7651251
/**
* @author ManagementAndJava
*/
/*
* 1.了解类在运行是的信息
* 1.1了解类的加载过程
* 1.2了解 JVM中 方法区(和其中含有的常量池) 栈区 堆区
*
*
* 1.了解JVM运行机制和类的运行时信息
* 1.1java内存分配分析:
* JVM是java程序与操作系统之间的桥梁,
* 一个完成的java程序运行时会涉及到以下内存区域:寄存器; 栈; 堆;方法区; 常量池;
* 1:栈:
* 保存局部变量的值:存放 基本数据类型的值 (非对应的包装器类型)
* int x=3;在栈内存中开辟一块地址为OXFF101的内存,里面存的值是3;
* 保存执行堆区对象或者常量池内对象的引用符号(指针),
* Integer x= 34;此时在方法区的常量池中开辟一个地址比如为(xof100)的内存,把数值34存放其中,在栈中开辟
* 一个地址为OF200的内存把引用符号x(指向堆中地址xof100)存入;
* Student s = new Student();和上面一样;
* 保存加载方法时的帧;
* 特点:
* 栈中的数据是共享的;
* 无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普
* 通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就
* 可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区
* 各占一块内存。
* 每个线程都有自己的栈区,数据都是私有的其他栈不能访问
* 2.堆:
* 用来存放动态产生的数据,比如new产生的对象,数组。
* 注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。
* 因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方
* 法复制一次;JVM只有一个堆区 被所有线程共享;
* 3.方法区:
* 用来存放已被加载的类的信息、常量、静态变量、即时编译器编译后的代码
* (在java中static的作用就是说明该变量,方法,代码块是属于类的还是属于实例的)。
* 又称为静态区,其和堆一样被所有线程共享;其存储的都是在整个线程中唯一的元素如 class 和static
* 4.常量池:
* JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。
* 包括直接常量(基本类型包装器,String)和对其他类型、方法、字段的符号引用(1)。
* 池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号
* 引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于方法区(Method Area)内
* ( 1)、存放字符串常量和基本类型变量,比如String str=”www”; 实际上”www”是在常量池里边。
* (2)、常量池是在方法区中而不是堆内存中。
* (3)、 Java的8种基本类型包装器(Byte, Short, Integer, Long, Character, Boolean, Float, Double),
* 除Float和Double以外, 其它六种都实现了常量池, 但是它们只在大于等于-128并且小于等于127时
* 才使用常量池。而如果大于127 或小于-128 则不会使用常量池所以会直接在堆内存中创建对象。。
*
*
* 因为在java的八种基本类型: 基本类型(包装器类型) (普通变量(类))
* boolean (Boolean) char (Character) byte(Byte) short(Short) int(Integer) long(Long)
* float(Float) double(Double)
*
* 简要总结:
* 对于局部变量(包括基本数据类型变量和引用变量(区分基本类型包装器变量)) 基本数据类型变量会在栈中直接存放其数值,
* 并且共享数值。引用变量,会在堆中创建对象,再栈中存放指向堆中地址的指针;而对于在-128——127之间的基本数据类型
* (6种再加上String)包装器对象,其数值存放在常量池中,引用存放在栈中;
*
* */
//java常量池运用如下:
class ConstantPool{
/*
* 在jvm规范中,每个类型 都有自己的常量池。常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段、
* 方法的符号引用。 之所以是符号引用而不是像c语言那样,编译时直接指定其他类型,是因为java是动态绑定的,只有在运行时根据某些规则才能
* 确定具体依赖的类型实例,这正是java实现多态的基础。
*/
//常量池中的对象和堆中的对象
public static void method(){
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
//i1和i2所对应的的对象分别位于 堆中 不同的内存空间
System.out.println(i1==i2);//输出结果为 false 因为 new在堆中 引用i1和i2是在栈中存放各自堆中不同的地址
int i3 =129;
int i4 = 129;
//变量的符号和数据都存放在栈中 并且只会在栈中存一份数据 i5=xxff102 i6=xxff102 同时指向129
System.out.println(i3==i4);//输出结果为true;因为是在栈中只创建了一个数据两个变量符号同一个地址;
/*
* java中基本类型的 包装类 的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,
* 另外两种 浮点数类型(Float Double) 的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型
* 的包装类也只是在对应值-128-127时才可以使用常量池。
* */
//5种整形的包装类Byte,Short,Integer,Long,Character的对象,
//在值小于127时可以使用常量池
Integer i5=127;
Integer i6=127;
//i5和i6对对应的常量127存在常量池中,并且由于常量池中数据共享,所以在常量池中只会存在一个 127;而i5和i6这两个
//变量符号是在栈中保存的(i5=xxffo12,i6=xxff012),并且指向常量池中同一个地址;
System.out.println(i5==i6);//输出true
//值大于127时,不会从常量池中取对象
Integer i7=128;
Integer i8=128;
//在堆内存中分别建立两个 128 变量符号i7和i8分别保存在栈内存中,并且指向不同的地址;i7=xxf101 i8 =xxff451;
System.out.println("i7==i8"+(i7==i8));//输出false
//Boolean类也实现了常量池技术
Boolean b1=true;
Boolean b2=true;
System.out.println("b1==b2"+(b1==b2));//输出true
//浮点类型的包装类没有实现常量池技术 因此其数值保存在堆中 栈中存放对应堆中的地址;
Double d1=1.0;
Double d2=1.0;
System.out.println("d1==d2"+(d1==d2));//输出false
//String也实现了常量池技术,String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术
String s1 = "helloJava";
String s2 = "helloJava";
System.out.println("s1 == s2 "+(s1==s2));//输出结果:true
String s3 = new String("hellojava");
String s4 = new String("hellojava");
//属于new对象的 对象建立在堆中 引用变量存贮在栈中 ,并且栈中引用变量存的是两个对象的地址;
System.out.println("s3 == s4"+(s3=s4));//输出结果必然 为false;
String s5 = "hello";
String s6 = "Java";
//String s7= s5+s6;
System.out.println("s5+s6==s1"+((s5+s6)==s1));//输出结果为false;
//在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象
final String s8 = "hello";
String s9 = s8+"java";
System.out.println("s8+java=s1 "+((s9==s1)));//输出结果为 false
final String s81 = "hello";
final String s91 = "java";
String s10 = s81+ s91;
System.out.println("s81+s91=s1 "+((s10==s1)));//输出结果为 false
final String s82 = "hello";
String s92 = "hello4";
String s11 = s82+ 4;
System.out.println("s82+4=s92 "+((s11==s92)));//输出结果为 true
String s83 = "hello";
String s93 = "hello4";
String s12 = s83+ 4;
System.out.println("s83+4=s93 "+((s12==s93)));//输出结果为 false
//思考为什么从 s5到s13的实例中会出现不同的结果:
Integer in1=30;
Integer in2 =1;
Integer in3 =31;
System.out.println(in3==in2+in1);//输出结果为true;Java的数学计算是在内存栈里操作的其实比较的是
//基本类型(31=30+1),他们的值相同,因此结果为True。
}
}
class Person1{//编译时其类型信息都会放入方法区
private String name;//运行时 new Person1实例后 name 应有放在自己私有的栈中 ,name 对象放在堆区里
public Person1(String name){
this.name =name;
}
public void eat(){//eat方法本身放入方法区中;
System.out.println("i can eat");
}
}
public class MemoryAllocation {
/*
* 系统收到开始命令后,启动JVM,这个进程首先从classpath路径中找到ReflectTest.class文件,读取这个文件中的二进制
* 数据,然后将运行时的ReflectTest类的类信息存放到方法区中;(上述过程也被成为类的加载过程),紧接着JVM会从方法区
* 中找打main()方法开始执行;
* */
public static void main(String[] args) {
Person1 p1 = new Person1("Mike");
/*当JVM读到这句话时,首先回去方法区中找Person1的信息,由于第一次加载发现没有,此时JVM会立即加载Person1L类,并且
* 把Person1类的类型信息存放在方法区中,Java虚拟机首先就是在堆区中为一个新的Person1实例分配内存, 这个Person1实例
* 持有着指向方法区的Person1类的类型信息的引用。实际上指的是Person1类的类型信息在方法区中的内存地址, 而这个地址,
* 就存放了在Person1实例的数据区里。
*
* 在虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被
* 称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过
* 中的临时数据。
*
* p1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方
* 法调用栈中。而“=”将把这个p1变量指向堆区中的Person1实例,也就是说,它持有了引用。
* */
//p1.eat();
/*
* 接下来JVM执行P1.eat()方法时,JAVA虚拟机根据局部变量p1持有的引用,定位到堆区中的Person1实例,再根据Person1实例持有的引用,
* 定位到方法去中Person1类的类型信息,从而获得eat()方法的字节码,接着执行eat()方法包含的指 令。
* */
ConstantPool.method();
}
}
相关推荐
基于QT的华为网络摄像头二次开发
第一次使用华为的网络摄像头并进行二次开发,网上关于QT对华为网络摄像头的二次开发的文章很少,基于项目的需求做了一些工作,特此记录。 目标: 1、实时预览 2、手动控制录制视频 3、监听告警型号 4、实时获取元数据中的划定区域内的人数 摄像头型号如下: 准备工作: 在购买摄像头后,应当在官网下载对应的开发资料,如果需要权限,则联系华为的技术支持人员。下载资料如下: SDC Development Kit Demo 8.0.T9 SDK DEMO下载地址:https://bbs.hua
Java内存分配以及数组使用常见问题:
3. 数组使用常见问题 问题1 : 如果访问的元素位置超过数组的最大索引,执行时会出现ArrayIndexOutOfBoundsException(数组索引越界异常)。 问题2 : 如果数组变量中没有存储数组的地址,而是null,在访问数组信息时会出现NullPointerException(空指针异常)。
数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例
数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例
Java内存分配策略
Java内存分配策略
模电专题-MOS管的放大电路分析
在实际应用中,我们经常会使用到功率MOS,这时通常不会将它当成一个开关使用,而是当成一个放大器来使用,那这就需要让其工作在放大状态。参考下图中的mos管的特性曲线,右图中的输出特性曲线中有一根红色的分界线,这个线就是区分mos管工作状态的分界线,在红线的左边,mos管工作在可变电阻区,也就是线性区;在红线的右边mos管工作在恒流区,也就是饱和区。当然,还有一个截止区。本文分析主要运用模电课本中的理论计算验证。
Python金融数据获取工具库之baostock使用详解
在金融数据分析和量化交易中,获取准确及时的市场数据是非常重要的。baostock是一个专门为中国股市数据提供支持的 Python 库,它提供了免费的股票数据接口,用户可以方便地获取股票、指数、基金等各种金融数据。本文将详细介绍baostock库,包括其安装方法、主要特性、基本和高级功能,以及实际应用场景,帮助全面了解并掌握该库的使用。
Java的内存分配
首先,main方法会先进入栈里面,然后再执行student的这个实例化,student这个对象就被创建,创建后会被加载到栈里面,在栈里面student这个对象就会去找堆中new的Student类型,然后堆会给student的属性一个默认的值,name是null,不同的类型默认值不同,然后用户自定义再给name赋值,name的值就可以输出了,执行完这个程序,这个student就会出栈,然后main方法也出栈了。注意:每一个new出来的东西都有一个地址值,使用完毕,会在垃圾站回收器空间时被回收。
⑩电子产品拆解分析-家用无线遥控开关433Mhz
①免布线随意贴,装上就能使用解决单线开关烦恼;②遥控配对简单,无线通讯距离长,信号可穿墙;
【JVM】详解Java内存区域和分配
C/C++需要自行回收和释放已经没用的对象,但是对于Java程序员来说,在虚拟机自动内存管理机制的帮助下, 不再需要为每一个new操作去写对应的free代码,就如同吃完饭之后不需要自己收拾盘子一样。看起来一切都师范的美好,但是一旦出现内存泄漏和溢出,如果不了解虚拟机是如何使用内存的,那么排查错误、纠正问题就会是一个艰难的问题。
基于sklearn实现LDA主题模型(附实战案例)
目录LDA主题模型1.LDA主题模型原理2.LDA主题模型推演过程3.sklearn实现LDA主题模型(实战)3.1数据集介绍3.2导入数据3.3分词处理 3.4文本向量化3.5构建LDA模型3.6LDA模型可视化 3.7困惑度 其实说到LDA能想到的有两个含义,一种是线性判别分析(Linear Discriminant Analysis),一种说的是概率主题模型:隐含狄利克雷分布(Latent Dirichlet Allocation,简称LDA)。 现在讨论的是主题模型
按照CANoe模板制作seed&&key.dll
在canoe进行诊断测试的时候,在0x27服务中需要制作一个dll文件。可在canoe的诊断中进行加载,也可用于diva的自动化测试。 本文按照canoe提供的KeyGenDll_GenerateKeyEx模板制作。 KEYGENALGO_API VKeyGenResultEx GenerateKeyEx( const unsigned char* iSeedArray, /* Array for the seed [in] */ unsigned int
3、java函数和数组
**1.**类,类就是同一类事物的统称。是抽象的。如:鸟类,虫类,家禽类等。 类就是封装对象属性和行为的载体,反过来说就是:具有相同属性和行为的实体被成为类。 如果面临实际问题,通常需要实例化对象来解决问题。Persnoal p = new personal(); 2. 成员变量:在java中,对象的属性也被称为成员变量。成员方法:成员方法可以有参数可以没有,可有返回值也可没有。一般类中都会写上s...
Devexpress16.2.6破解工具
Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具
Java基础04:数组、二维数组
数组介绍 数组(array)是一种容器,用来存储(同种数据类型)的多个值。 理解:容器类型为int,存储double类型,存在问题 理解:容器类型为int,存储byte类型,没有问题 建议:容器的类型,和存储的数据类型保持一致 数组定义格式 初始化 Java中的数组必须先初始化,然后才能使用 所谓初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。 动态初始化 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值 格式:数据类型 [ ] 变量名 = new 数据类型[数组长度]; 范
win10 跳过U8环境检测的IE WebControls.rar
win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。
Outlook Express 6 (OE6) for Win7/Win8/Win10
英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。
【Java语言学习(四)】
数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致。 数据类型[] 数组名int[] arr;//定义了一个int类型的数组,数据名是arrchar[] arr;java中的数组必须先初始化后才能使用,所谓初始化,就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。数组动态初始化就是只给定数组的长度,由系统给出默认初始化值 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始。 这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。
假人有限元模型
假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用
Java学习笔记(02_2函数与数组)
知识点总结于毕向东Java基础视频教程25天版本,侵权请联系删除。 第三章:函数与数组函数函数的定义函数的特点函数的应用函数的重载数组数组的定义数组的内存分配及特点数组内存结构内存结构栈内存堆内存数组操作常见问题数组常见操作数组中的数组 函数 函数的定义 什么是函数? 函数就是定义在类中的具有特定功能的一段独立小程序。 函数也称为方法。 函数的格式 修饰符返回值类型函数名(参数类型形式参数1,参数类型形式参数2,) { 执行语句; return 返回值; } 返回值类型:函数运行后的结果
Java基础-数组
Java基础-数组1.数组1.1什么是数组【理解】1.2数组定义格式【记忆】1.2.1第一种1.2.2第二种1.3数组动态初始化【应用】1.3.1什么是动态初始化1.3.2动态初始化格式1.3.3动态初始化格式详解1.4数组元素访问【应用】1.4.1什么是索引1.4.2访问数组元素格式1.4.3示例代码1.5内存分配【理解】1.5.1内存概述1.5.2java中的内存分配1.6单个数组的内存图【理解】1.7多个数组的内存图【理解】1.8多个数组指向相同内存图【理解】1.9数组静态初始化【应用】1.9.1什么
Java萌新必看:编译错误自救指南
最近在辅导学弟学妹学Java时,发现很多人第一次遇到'内部Java编译器错误'就手足无措。作为过来人,我整理了这个超实用的自救指南,用最直白的方式帮你理解这个报错。这个平台最方便的是不用配环境,直接在线修改代码就能看到效果。我带着学生测试时发现,切换JDK版本后错误信息会实时变化,特别适合理解版本兼容性问题。假设我们有个简单的HelloWorld程序,但用了Java 8的语法,却用Java 11的编译器运行。:就像用新钥匙开旧锁,当你的JDK版本和项目要求的版本不一致时最容易出现这个问题。
【小白学java】D06》》》初识 数组Array
一、了解数组(一维数组) 1、概述: 数组(array)是一种用于存储多个相同类型数据的存储模型 2、数组的定义格式 有两种定义格式 格式1: 数据类型[] 变量名 例如: int[] arr 格式2: 数据类型 变量名[] 例如: int arr[] 3、数组的初始化(动态初始化) 初始化 :
Java--数组
Java语言基础(数组概述和定义格式说明) A:为什么要有数组 数组是存储多个变量的东西 这多个变量的数据类型要一致 B:数组概念 数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。 数组既可以存储基本数据类型,也可以存储引用数据类型 C:数组定义格式 格式1: 数据类型[] 数组名; 格式2: 数据类型 数组名[]; 举例: int[] a; 定义了一个in...
05 Java数组
本文介绍了Java中数组的基本概念和使用方法。主要内容包括:数组的定义(相同类型数据的有序集合)、声明创建方式(静态/动态初始化)、内存分析、多维数组结构、Arrays工具类的常用方法(排序、填充等)、冒泡排序算法实现,以及稀疏数组的应用场景。特别强调了数组作为对象在堆中存储、长度不可变、下标从0开始等特点,并提供了数组遍历、反转、多维数组操作等实用代码示例。最后通过棋盘案例演示了稀疏数组如何有效压缩存储稀疏数据。
从0开始的java开发学习(day03)
在调用float的时候最好完全使用浮点数进行比较也就是定义了a和a+1进行比较。
一维数组的介绍
数组介绍 1、数组(array)是一种容器,用来存储(同种数据类型)的多个值; 2、应用场景:要操作的数据,是同一组数据,可以使用数组容器进行存储; 3、总结:数组容器在存储数据的时候,需要结合数据类型考虑。容器的类型和存储的数据类型保持一致。 例如:int类型的数组容器(boolean,byte,short,double) 数组的定义格式 数组的定义格式 格式一:数据类型[ ] 变量名 例如:int[ ] array 格式二:数据类型 变量名[ ] 例如:int array[ ] 数组初
Eclipse运行时提示failed to create the java virtual machine 如何解决
几经周折终于找到了解决办法,特与朋友们分享,方法如下: 找到eclipse目录下的eclipse.ini,可以看到如下内容: -startup plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86
Java学习第二周基础知识总结(二)
目录 1.方法 1.1 方法的概念 1.2 方法的格式 1.3 方法的调用 例题 1.4方法的重载 定义: 2.数组 2.1 数组的概念 2.2 数组定义的格式 2.3 数组的初始化 数组初始化的方式 动态初始化格式; 静态初始化格式: 2.4 数组中常见的两个小问题 2.5 Java中的内存分配 2.6 二维数组 定义格式: 二维数组的初始化 练习 2.7数组的高级排序:冒泡排序 1.方法 1.1 方法的概念 就是将一个功能抽取出来,把代码单独定..
Java基础——数组1
Java基础——数组
3168



被折叠的 条评论
为什么被折叠?



