Java 应用与开发 - Java 内存模型与分配机制大纲 Java 内存模型 Java 程序内存运行分析 Java 内存管理建议 Java 应用与开发 Java 内存模型与分配机制 王晓东 wangxiaodong@ouc.edu.cn 中国海洋大学 September 30, 2018 大纲 Java 内存模型 Java 程序内存运行分析 Java 内存管理建议 学习目标 1. 理解 JVM 内存模型,掌握 JVM 内存构成 2 虚拟机(Java Virtual Machine, JVM) ▶ Java 程序运行在 JVM 上,JVM 是程序与操作系统之间的桥梁。 ▶ JVM 实现了 Java 的平台无关性。 ▶ JVM 是内存分配的前提。 类装载子系统 Class文件 Class文件 Class文件 方法区 Java堆 Java栈 程序计数器 本地方法栈 执行引擎 本地接口 通过全限定名装载 操作系统 操作系统本地库0 码力 | 44 页 | 818.30 KB | 1 年前3
 《Java 应用与开发》课程讲义 - 王晓东二维数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.3.1 二维数组的声明和内存分配 . . . . . . . . . . . . . . . . . . . . . . 23 3.3.2 二维数组定义的含义 . . . . . . . . . . . . . . . . . 5.5 课后习题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6 Java 内存模型与分配机制 58 6.1 Java 内存模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 6.1.1 Java 分为源代码级(需重新编译源代码,如 C/C++)和目标代码级 (Java) 平台 无关。 分布式 可支持分布式技术及平台开发。 可靠性 不支持直接操作指针,避免了对内存的非法访问;自动单元回收功能防止内存 丢失等动态内存分配导致的问题;解释器运行时实施检查,可发现数组和字符串 访问的越界;提供了异常处理机制。 . . . . . . . . . . . . . . . . . . . . . . . . . . .0 码力 | 330 页 | 6.54 MB | 1 年前3
 Apache Shiro 1.2.x Reference Manual 中文翻译Shiro却不是这样子的。一个好的安全框架应该屏蔽复杂性,向外暴露简单、直观的API,来 简化开发人员实现应用程序安全所花费的时间和精力。 Shiro能做什么呢? 验证用户身份 用户访问权限控制,比如: 判断用户是否分配了一定的安全角色。 判断用户是否被授予完成某个操作的权限 在非 web 或 EJB 容器的环境下可以任意使用Session API 可以响应认证、访问控制,或者 Session 生命周期中发生的事件 际和安 全相关的数据如用户执行身份认证(登录)的帐号和授权(访问控制)进行交互,Shiro 从一个或多个程序配置的 Realm 中查找这些东西。 Realm 本质上是一个特定的安全 DAO:它封装与数据源连接的细节,得到Shiro 所需的相关的数据。在配置 Shiro 的时 候,你必须指定至少一个Realm 来实现认证(authentication)和/或授权 (authorization)。SecurityManager 管模块化, SecurityManager(包括它的继承类)并没有做到,相反地,SecurityManager实现更像一个 轻量级的‘容器(container)’,代表几乎所有嵌套/封装组件的行为,这种‘封装(wrapper)’设 计在上面的架构图表中已有反映。 Apache Shiro 1.2.x Reference Manual 中文翻译 22 3. Architecture 架构0 码力 | 196 页 | 2.34 MB | 1 年前3
 Hello 算法 1.0.0b2 Java版3. 两种实现对比 支持操作 两种实现都支持栈定义中的各项操作,数组实现额外支持随机访问,但这已经超出栈的定义范畴,一般不会用 到。 时间效率 在数组(列表)实现中,入栈与出栈操作都是在预先分配好的连续内存中操作,具有很好的缓存本地性,效率 很好。然而,如果入栈时超出数组容量,则会触发扩容机制,那么该次入栈操作的时间复杂度为 ?(?) 。 在链表实现中,链表的扩容非常灵活,不存在上述数 数组实现的栈在触发扩容时会变慢,但由于扩容是低频操作,因此 总体效率更高; ‧ 链表实现的栈可以提供 更加稳定的效率表现; 5. 栈与队列 hello‑algo.com 66 空间效率 在初始化列表时,系统会给列表分配“初始容量”,该容量可能超过我们的需求。并且扩容机制一般是按照特 定倍率(比如 2 倍)进行扩容,扩容后的容量也可能超出我们的需求。因此,数组实现栈会造成一定的空间浪 费。 当然,由于结点需要额外存储指针,因此 89 6.2.1. 哈希表扩容 哈希函数的最后一步往往是对桶数量 ? 取余,以将哈希值映射到桶的索引范围,从而将 key 放入对应的桶中。 当哈希表容量越大(即 ? 越大)时,多个 key 被分配到同一个桶中的概率就越低,冲突就越少。 因此,在哈希表内的冲突整体比较严重时,编程语言一般通过扩容哈希表来缓解。与数组扩容类似,哈希表扩 容需要将所有键值对从原哈希表移动至新哈希表,开销很大。0 码力 | 197 页 | 15.72 MB | 1 年前3
 Hello 算法 1.2.0 简体中文 Java 版我们可以将数据结构与算法类比为拼装积木,积木代表数据,积木的形状和连接方式等代表数据结构, 拼装积木的步骤则对应算法。 1. Q & A Q:作为一名程序员,我在日常工作中从未用算法解决过问题,常用算法都被编程语言封装好了,直接用就 可以了;这是否意味着我们工作中的问题还没有到达需要算法的程度? 如果把具体的工作技能比作是武功的“招式”的话,那么基础科目应该更像是“内功”。 我认为学算法(以及其他基础科目) 。 ‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(1) = 1 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。 着最初被调用的函数实际上是最后完成其求和操作的,这种工作机制与栈的“先入后出”原则异曲同工。 事实上,“调用栈”和“栈帧空间”这类递归术语已经暗示了递归与栈之间的密切关系。 1. 递:当函数被调用时,系统会在“调用栈”上为该函数分配新的栈帧,用于存储函数的局部变量、参数、 返回地址等数据。 2. 归:当函数完成执行并返回时,对应的栈帧会被从“调用栈”上移除,恢复之前函数的执行环境。 因此,我们可以使用一个显式的栈来模拟调用栈的行为,从而将递归转化为迭代形式:0 码力 | 379 页 | 18.48 MB | 10 月前3
 Hello 算法 1.1.0 Java版。 ‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(1) = 1 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。 着最初被调用的函数实际上是最后完成其求和操作的,这种工作机制与栈的“先入后出”原则异曲同工。 事实上,“调用栈”和“栈帧空间”这类递归术语已经暗示了递归与栈之间的密切关系。 1. 递:当函数被调用时,系统会在“调用栈”上为该函数分配新的栈帧,用于存储函数的局部变量、参数、 返回地址等数据。 2. 归:当函数完成执行并返回时,对应的栈帧会被从“调用栈”上移除,恢复之前函数的执行环境。 因此,我们可以使用一个显式的栈来模拟调用栈的行为,从而将递归转化为迭代形式: 表格,其中每个单元格都可以存储一定大 小的数据。 第 3 章 数据结构 hello‑algo.com 53 系统通过内存地址来访问目标位置的数据。如图 3‑2 所示,计算机根据特定规则为表格中的每个单元格分配 编号,确保每个内存空间都有唯一的内存地址。有了这些地址,程序便可以访问内存中的数据。 图 3‑2 内存条、内存空间、内存地址 Tip 值得说明的是,将内存比作 Excel 表格是一个简化的0 码力 | 378 页 | 18.47 MB | 1 年前3
 Hello 算法 1.0.0 Java版。 ‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(1) = 1 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。 着最初被调用的函数实际上是最后完成其求和操作的,这种工作机制与栈的“先入后出”原则异曲同工。 事实上,“调用栈”和“栈帧空间”这类递归术语已经暗示了递归与栈之间的密切关系。 1. 递:当函数被调用时,系统会在“调用栈”上为该函数分配新的栈帧,用于存储函数的局部变量、参数、 返回地址等数据。 2. 归:当函数完成执行并返回时,对应的栈帧会被从“调用栈”上移除,恢复之前函数的执行环境。 因此,我们可以使用一个显式的栈来模拟调用栈的行为,从而将递归转化为迭代形式: 表格,其中每个单元格都可以存储一定大 小的数据。 第 3 章 数据结构 hello‑algo.com 53 系统通过内存地址来访问目标位置的数据。如图 3‑2 所示,计算机根据特定规则为表格中的每个单元格分配 编号,确保每个内存空间都有唯一的内存地址。有了这些地址,程序便可以访问内存中的数据。 图 3‑2 内存条、内存空间、内存地址 � 值得说明的是,将内存比作 Excel 表格是一个简化的类比,实际内存的工作机制比较复杂,涉0 码力 | 376 页 | 17.59 MB | 1 年前3
 Hello 算法 1.0.0b5 Java版‧ 递归:将问题分解为子问题 ?(?) = ?+?(?−1) ,不断(递归地)分解下去,直至基本情况 ?(0) = 0 时终止。 1. 调用栈 递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。 这将导致两方面的结果。 ‧ 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归 通常比迭代更加耗费内存空间。 Excel 表格,其中每个单元格都可以存储一定大小的数据, 在算法运行时,所有数据都被存储在这些单元格中。 系统通过内存地址来访问目标位置的数据。如图 3‑2 所示,计算机根据特定规则为表格中的每个单元格分配 编号,确保每个内存空间都有唯一的内存地址。有了这些地址,程序便可以访问内存中的数据。 图 3‑2 内存条、内存空间、内存地址 内存是所有程序的共享资源,当某块内存被某个程序占用时,则无法被其他程序同时使用了。因此在数据结 字符,包括各种语言的字符、符号、甚至是表情符号等。在庞大的 Unicode 字符集中,常用的字符占用 2 字 节,有些生僻的字符占 3 字节甚至 4 字节。 Unicode 是一种字符集标准,本质上是给每个字符分配一个编号(称为“码点”),但它并没有规定在计算机 中如何存储这些字符码点。我们不禁会问:当多种长度的 Unicode 码点同时出现在同一个文本中时,系统 如何解析字符?例如给定一个长度为 2 字节的编码,系统如何确认它是一个0 码力 | 376 页 | 30.69 MB | 1 年前3
 Hello 算法 1.0.0b4 Java版表格,其中每个单元格都可以存储 1 byte 的数据,在 算法运行时,所有数据都被存储在这些单元格中。 系统通过「内存地址 Memory Location」来访问目标内存位置的数据。计算机根据特定规则为表格中的每 个单元格分配编号,确保每个内存空间都有唯一的内存地址。有了这些地址,程序便可以访问内存中的数 据。 Figure 3‑2. 内存条、内存空间、内存地址 内存是所有程序的共享资源,当内存被某个程序占用时,其 字符,包括各种语言的字符、符号、甚至是表情符号等。在庞大的 Unicode 字符集中,常用的字符占用 2 字 节,有些生僻的字符占 3 字节甚至 4 字节。 Unicode 是一种字符集标准,本质上是给每个字符分配一个编号(称为“码点”),但它并没有规定在计算机 中如何存储这些字符码点。我们不禁会问:当多种长度的 Unicode 码点同时出现在同一个文本中时,系统 如何解析字符?例如,给定一个长度为 2 字节的编码,系统如何确认它是一个 数组存储在栈上和存储在堆上,对时间效率和空间效率是否有影响? 栈内存分配由编译器自动完成,而堆内存由程序员在代码中分配(注意,这里的栈和堆和数据 结构中的栈和堆不是同一概念)。 1. 栈不灵活,分配的内存大小不可更改;堆相对灵活,可以动态分配内存。 2. 栈是一块比较小的内存,容易出现内存不足;堆内存很大,但是由于是动态分配,容易 碎片化,管理堆内存的难度更大、成本更高。 3. 访问栈比0 码力 | 342 页 | 27.39 MB | 1 年前3
 Nacos架构&原理
数据,方便与三方监控系统打通。  Trace:暴露标准 Trace,方便与 SLA 系统打通,日志白平化,推送轨迹等能力,并且可以和计 量计费系统打通。  接入管理:相当于阿里云开通服务,分配身份、容量、权限过程。  用户管理:解决用户管理,登录,SSO 等问题。  权限管理:解决身份识别,访问控制,角色管理等问题。 Nacos 架构 < 20  审计系统:扩展接口方便与不同公司审计系统打通。 。配置分组的常见场 景:不同的应用或组件使用了相同的配置项,如 database_url 配置和 MQ_Topic 配置。 配置 ID(Data ID) Nacos 中的某个配置集的 ID。配置集 ID 是划分配置的维度之⼀。Data ID 通常用于划分系统的配 置集。⼀个系统或者应用可以包含多个配置集,每个配置集都可以被⼀个有意义的名称标识。Data ID 尽量保障全局唯⼀,可以参考 Nacos Spring 。如果同⼀个环境内想配置相同的配置,可以通过 Group 来区分。如下图所示: Nacos 架构 < 26 从多个租户的角度来看,每个租户都可以有自己的命名空间。我们可以为每个用户创建⼀个命名空 间,并给用户分配对应的权限,比如多个租户(zhangsan、lisi、wangwu),每个租户都想有⼀套 自己的多环境配置,也就是每个租户都想配置多套环境。那么可以给每个租户创建⼀个 Namespac e (z0 码力 | 326 页 | 12.83 MB | 10 月前3
共 29 条
- 1
 - 2
 - 3
 













