指针初始化

JVM类加载机制

廉价感情. 提交于 2020-04-08 08:46:30
JVM类加载机制 JVM类加载机制分为:加载,验证,准备,解析,初始化五步,如 下图: 加载:这个阶段会在内存中生成一个代表这个类的java.lang.Class对象作为方法区这个类的各种数据的入口。 验证:目的去报Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身安全。 准备:该阶段为类变量分配内存并设置类变量的初始值,即在 方法区中分配这些变量所使用的内存空间。 解析:指虚拟机将常量池中的符号引用替换为直接引用的过程(比如说方法的符号引用,是有方法名和相关描述符组成,在解析阶段,JVM把符号引用替换成一个指针,这个指针就是直接引用,它指向该类的该方法在方法区中的内存位置) 初始化:为类的静态变量赋予正确的初始值。当静态变量的等号右边的值是一个常量表达式时,不会调用static代码块进行初始化。只有等号右边的值是一个运行时运算出来的值,才会调用static初始化. 以下几种情况不会执行初始化操作 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化 定义对象数组,不会触发该类的初始化 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触 发定义常量所在的类 通过类名获取Class 对象,不会触发类的初始化 通过Class.forName 加载指定类时,如果指定参数initialize 为false 时

JVM内容整合

爱⌒轻易说出口 提交于 2020-04-08 00:48:55
前言: JVM全称Java Virtual Machine是虚构的计算机,也是因此Java才可在各个系统平台运行,本文内容篇幅较长主要分为JVM整体流程,内存划分及组成以及JVM机制等方面进行介绍     一、JVM整体流程 一个java文件执行的大致步骤流程如下: 一张复杂的JVM架构图:   JVM加工类过程 加载 将class字节码文件加载进虚拟机,存储至元空间的方法区内 验证 文件格式验证 元数据验证 字节码验证 符号引用验证 准备 为类变量(static修饰)分配内存并设置初始值(指JVM默认值,例如:引用类型为null,int类型为0,不是类中指定的值) 如果类变量被final修饰,则直接赋类中定义的默认值(特殊情况:该final静态变量如果需要计算,会导致初始化) 成员变量(实例变量、属性、属于对象)不分配内存 解析 将常量池的符号引用转为直接引用(由于java为值传递,去掉了指针) 初始化 给类变量赋值(类中定义的默认值) 初始化静态语句块   相关题目测试 class GrandParent3{ static { System.out.println("GrandParent3静态代码块"); } } class Parent3 extends GrandParent3{ public final static String parent3="hello

C#学习笔记(一)

谁说我不能喝 提交于 2020-04-07 05:37:46
C#学习笔记(一):C#与C++语法的一些不同 1,C#中没有了"::"的域操作符,全部用了"."了。但是继承还是用的":",C#的"::"是用作命名空间别名的修饰符。 2,在C#中变量使用前必须初始化,程序员显式的或者编译器自动的。其中:变量是类或者结构中的字段,如果没有显式初始化,则在默认创建这些变量的时候其值就是0。然而方法的局部变量必须在代码 中显式初始化。(这与C++中不同)。 3,例如对于下面语句:SomeType obj;在C++这个是一个值类型,会在堆栈中创建一个SomeType的实例。但是在C#中这个只会为SomeType对象创建一个引用,这个引用还没有指向任何的对象。也就不能调用它的方法。然而C#中实例化对象要使用new关键字,将对象存储在堆上。返回一个引用。 4,下面的代码: public static in Mian() { int j = 20; for (int i = 0; i < 10; i++) { int j = 30; //....use value j... } } 与C++不同的是这个时候C#不能隐藏for循环的变量:j,前面的j还在定义域中。但是对于下面代码: static int j = 20; public static void Main() { int j = 30; //....use j } 这个就是可以的,这个是静态变量

对象创建的过程

混江龙づ霸主 提交于 2020-04-06 06:21:24
通过符号引用定位到类是否被加载。没有就加载类。执行类加载与验证的过程 分配内存:类的准备阶段。类加载完成后就能确定对象分配多少内存。如果虚拟机具有 Compact 压缩功能(标记整理),就是用 指针碰撞 (记录头尾位置);如果只有 标记清理 的虚拟机,就是用 空闲列表 。 分配内存的方式: CAS 与 TLAB 两种。如果多线程并发创建,需要考虑同步问题(多个对象指向一个地方)。 CAS:一般使用 CAS 和失败重试保证原子性。 TLAB :按照线程分配不同空间(本地线程分配缓冲),只有 TLAB 用完,需要分配新的才需要同步。是否使用该方式通过参数指定 解析,符号引用替代成直接引用 初始化 分配到的内存初始化为零(除了对象头)。这就是对象属性不需要初始化可以直接使用 设置对象头:什么类的对象,元数据,哈希码,对象GC分代年龄等信息。根据虚拟机运行状态,判断是否启用偏向锁 执行初始化方法:<init>。按照程序员指定的初始化过程初始化对象。这里就是执行初始化的过程 父类的静态初始化块 本类的静态初始化块 父类的初始化块 父类的构造方法 本类初始化块 本类的构造方法 来源: oschina 链接: https://my.oschina.net/u/3870422/blog/3220397

Golang数组指针和指针数组

♀尐吖头ヾ 提交于 2020-04-04 22:49:49
数组很简单,有PHP基础一看就会,和PHP数组大不一样,不同的就是只有数字索引key,并且要指定类型 声明和初始化示例: package main import "fmt" func main() { // 声明 var arr1 [5]int arr1 = [5]int{1,2,3,4,5} // 声明并初始化 var arr2 [5]int = [5]int{1,2,3,4,5} // 直接初始化,只能在函数里 arr3 := [5]int{1,2,3,4,5} fmt.Println(arr1, arr2, arr3) } 数组循环,主要是for 和 for range 具体网上搜索一些会有很多教程,本文就不详细说,现在来点难的: 数组指针和指针数组: package main import "fmt" // 声明整形数组指针类型,表示该类型变量里存储的是一个数组的首地址 type arrPoint *[6]int func main() { // 声明并初始化数组,大小为6个元素整形数组,前5个数字是0,最后一个2 var a = [6]int{5: 2} var a1 = [6]int{5: 3} // 数组指针,变量的内容是数组的地址 var b arrPoint = &a var b1 arrPoint = &a1 // 指针数组,大小为2元素类型为arrPiont

[No000018A]改善C#程序的建议11-20

别说谁变了你拦得住时间么 提交于 2020-04-03 18:32:04
建议11:区别对待 == 和Equals CLR中将“相等性”分为两类: 1、值相等性:两个变量包含的数值相等。 2、引用相等性:两个变量引用的是内存中的同一个对象。 但并不是所有的类型的比较都是按照其本身,比如string是一个特殊的引用类型,但是在FCL中,string的比较就被重载为针对“类型的值”的比较,而不是“引用本身”的比较。对于自定义类型来说,如果想要实现这样的值比较而不是引用比较的话,则需要重载Equals方法,比如对于Person类,如果IDCode相同,我们可以认为他们是同一个人。 class Person { public string IDCode { get; private set; } public Person(string idCode) { this.IDCode = idCode; } public override bool Equals(object obj) { return IDCode == (obj as Person).IDCode; } } 此时通过Equals去比较的话,则就会通过重载后的方法来进行了。 object a = new Person("ABC"); object b = new Person("ABC"); Console.WriteLine(a == b); //False Console.WriteLine

u-boot-1.1.6第2阶段入口函数start_armboot分析

妖精的绣舞 提交于 2020-04-03 17:58:10
学习目标: 1、分析u-boot-1.1.6第2阶段入口函数void start_armboot (void),熟悉该函数所实现的功能 2、为后面能够掌握u-boot-1.1.6如何启动内核过程打下基础 前面通过对uboot第一阶段代码的分析,我们了解的uboot第一阶段所做的一些工作,并且找到了其第二阶段的入口函数void start_armboot(void)。为了能够在清楚理解uboot启动内核的机制,还需要对第二阶段代码进行分析。第二阶段入口函数void start_armboot(void)存放在board.c文件中,该文件位于uboot根目录下的lib_arm文件夹中。 1.gd_t数据结构分配内存 /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); //为gd_t结构体变量开辟空间 /* compiler optimization barrier needed for GCC >= 3.4 */ //并使得gd指针指向该空间初始位置 __asm__ __volatile__("": : :"memory"); memset ((void*)gd, 0, sizeof (gd

STL中vector的初始化

我与影子孤独终老i 提交于 2020-04-02 07:36:36
vector可用于代替C++中的数组,一般一致认为应该多用vector,因为它的效率更高,而且具备很好的异常安全性。而且vector是STL推荐使用的默认容器,STL中向量是使用数组实现的,因此向量具有顺序表的特点,可以快速随机存取数据。向量是一种数据类型的对象的集合,每个对象根据其位置有一个整数索引值与其对应,类似于数组。 使用向量之前,必须包含相应的头文件: #include<vector> using std::vector 同时也应当注意,vector是一个模板类,而非数据类型。所以在定义对象时必须说明vector保存的对象类型。以下给出一些初始化的例子: 1 vector<int> v; //定义向量对象 2 vector<int> v(v1); //定义向量对象v,并且用v1初始化 3 vector<int> v2(n,i); //定义向量对象v2,包含了n个值为i的元素 4 vector<int> v3(n); //定义向量对象v3,其中包含了n个元素值为0的元素 接着介绍一种使用数组初始化向量元素的方式,这种方式在刷题时非常常见,有必要掌握: 1 #include "stdafx.h" 2 #include <stdio.h> 3 #include <string.h> 4 #include <iostream> 5 #include <vector> 6

星号的秘密

北慕城南 提交于 2020-03-30 17:20:42
1 、乘法运算符 2 、定义指针 int *p = 0; 还是 int* p = 0;? 后一种比较容易这样理解:定义了一个变量p,它是指针型的(更详细一点,是指向int的指针型),相比而言,前面一种定义似乎是定义了*P这个奇怪的东西。但是后面一种写法会带来一个容易产生的误解: int* p1, p2; 这儿给人的感觉似乎是定义了两个指针型变量p1和p2,但是,事实上,这种直觉是错误的,正确的理解方式是int *p1, p2;即p1是指针型的,而p2确是整型的。 在MS VC++ 6.0中,是按照后面一种格式写的。 3 、何谓指针? 指针仅仅表示一个内存中的某个地址? 非也,注意到,我们在定义指针的时候,都关联了一个类型,如int,char,或者是string等等,如果说指针仅仅表示一个内存中的地址,那何必要关联这么多变化的东西呢?完全可以DWORD p=0;这样解决问题。 关联了的数据类型是作何用的呢? 它可以指示编译器怎样解释特定地址上内存的内容,以及该内存区域应该跨越多少内存单元。如 int *p; 编译器可以从这个定义中获得信息:1、p指向的内存存放的是整型数据,2、由于该内存区域只存放了一个数据,跨越的内存区域为4个字节,即p+1的效果是跳过了四个字节。 另一个复杂一点的例子,如 struct a {int x1; short x2; a *next; } 定义指针 a

C++星号的含义

爷,独闯天下 提交于 2020-03-30 17:03:04
1 、乘法运算符 2 、定义指针 int *p = 0; 还是 int* p = 0;? 后一种比较容易这样理解:定义了一个变量p,它是指针型的(更详细一点,是指向int的指针型),相比而言,前面一种定义似乎是定义了*P这个奇怪的东西。但是后面一种写法会带来一个容易产生的误解: int* p1, p2; 这儿给人的感觉似乎是定义了两个指针型变量p1和p2,但是,事实上,这种直觉是错误的,正确的理解方式是int *p1, p2;即p1是指针型的,而p2确是整型的。 在MS VC++ 6.0中,是按照后面一种格式写的。 3 、何谓指针? 指针仅仅表示一个内存中的某个地址? 非也,注意到,我们在定义指针的时候,都关联了一个类型,如int,char,或者是string等等,如果说指针仅仅表示一个内存中的地址,那何必要关联这么多变化的东西呢?完全可以DWORD p=0;这样解决问题。 关联了的数据类型是作何用的呢? 它可以指示编译器怎样解释特定地址上内存的内容,以及该内存区域应该跨越多少内存单元。如 int *p; 编译器可以从这个定义中获得信息:1、p指向的内存存放的是整型数据,2、由于该内存区域只存放了一个数据,跨越的内存区域为4个字节,即p+1的效果是跳过了四个字节。 另一个复杂一点的例子,如 struct a {int x1; short x2; a *next; } 定义指针 a