• 关于

    混合计算模型不可用

    的搜索结果

回答

虽然现在有很多的人呼吁使用混合云,因其可以利用私有云与公有的好处。但混合云也不是完全没有缺点的,它仍旧包含了一些安全障碍,要谨记下面五个问题。 公有云提供商提供重要的资源,以确保其基础架构在终端用户需要时有效且可访问。尽管云提供商进了最大努力,问题仍不可避免。大量宣传的宕机事件突出了将应用运转在单一数据中心且没有在其他数据中心进行故障恢复的风险。云架构师需要跨数据中心的冗余来减缓单一数据中心宕机的影响。缺少冗余对于混合云来说可能是严重的安全风险,尤其是如果数据冗余备份没有跨数据中心分布。在数据中心之间转移虚拟机(VM)实例比在大型数据集之间容易的多。云架构师可以使用一个厂商的多个数据中心实现冗余,或者多个公共云厂商或者是混合云。同时可以用混合云改善业务连续性,因为这并不是实现这个模型的唯一原因。同时使用来自单一厂商的多个数据中心,你可以节省成本,达到减少类似风险的水平。 维护和证明混合云法规尊重从更加困难。你不但要确保你的公有云提供商和私有云提供商符合法规,而且你必须证明两个云之间的协调是顺从的。比如,如果你的企业处理支付卡数据,你可能能够证明你的内部系统和你的云提供商遵从支付卡行业数据安全标准(PaymentCardIndustryDataSecurityStandard(PCIDSS))。引入了混合云,你必须确保两个云之间的数据转移是受到保护的。此外,你还需要确保卡数据不会从一个私有云上的法规遵从数据中心转移到一个较少安全性的公有云存储系统。你内部系统使用的预防漏洞的方法可能不直接转化到公有云上。 你可能坚信你的公有云提供商能够始终如一的符合服务水平协议(SLA)中期望的详细说明,但是你的私有云是否有同样的SLA?如果没有,你可能需要基于两个云的期望创建SLA,很可能就是基于你自己的私有云了。在你的私有云的可用性和性能的显示工作负载下收集数据。集成公有云和私有云寻求潜在的问题都会破坏服务。例如,如果一个私有云的关键业务驱动在本地保持敏感和机密数据,然后你的SLA应该体现出在公有云中使用这些服务的限制性。 从业务角度,信息安全是管理管理风险的。云计算(尤其是混合云)使用新的应用程序接口(API),要求复杂的网络配置,并对传统的系统管理员的知识和能力范围造成挑战。这些因素引入了新型的威胁。云计算并不比内部基础架构一样安全,但是混合云是个复杂的系统,管理员在管理上有限的经验,可能就造成了风险。 现有的安全控制,像身份认证、授权和身份认证管理需要在公有云和私有云中共同工作。整合这些安全协议,你只能选择其一:在两个云中复制控制并保持安全数据同步,或者使用身份认证管理服务,提供单一的服务运转在云端。在计划和时间阶段分配足够的时间,以便解决这些相当复杂的整合问题。

问问小秘 2019-12-02 03:00:17 0 浏览量 回答数 0

回答

本文主要为您介绍容器服务 ACK 的常见应用场景。 DevOps 持续交付 最优化的持续交付流程 配合 Jenkins 帮您自动完成从代码提交到应用部署的 DevOps 完整流程,确保只有通过自动测试的代码才能交付和部署,高效替代业内部署复杂、迭代缓慢的传统方式。 能够实现: DevOps 自动化 实现从代码变更到代码构建、镜像构建和应用部署的全流程自动化。 环境一致性 容器技术让您交付的不仅是代码,还有基于不可变架构的运行环境。 持续反馈 每次集成或交付,都会第一时间将结果实时反馈。 推荐搭配使用: 云服务器 ECS + 容器服务 DevOps 基于云原生技术的机器学习 专注机器学习本身,快速实现从 0 到 1 帮助数据工程师在异构计算资源集群上轻松开发、部署机器学习应用,跟踪试验和训练、发布模型,自动集成多种数据部署在分布式存储系统,加速训练数据读写,无需关心繁琐部署运维,专注核心业务,快速从 0 到 1。 能够实现: 支持生态 内置对 TensorFlow、Caffe、 MXNet、Pytorch 等主流深度学习计算框架支持和优化。 快速弹性 一键部署机器学习开发、训练、推理服务,秒级启动和弹性伸缩。 简单可控 轻松创建、管理大规模 GPU 计算集群,并且可以监控 GPU 利用率等核心指标。 深度整合 无缝接入阿里云存储、日志监控和安全基础架构能力。 推荐搭配使用: 云服务器 ECS/GPU 服务器 EGS/高性能计算服务 (Alibaba Cloud HPC)+ 容器服务 + 对象存储 OSS/文件存储 NAS/CPFS 容器服务 微服务架构 实现敏捷开发和部署落地,加速企业业务迭代 企业生产环境中,通过合理微服务拆分,将每个微服务应用存储在阿里云镜像仓库帮您管理。您只需迭代每个微服务应用,由阿里云提供调度、编排、部署和灰度发布能力。 能够实现: 负载均衡和服务发现 支持 4 层和 7 层的请求转发和后端绑定。 丰富的调度和异常恢复策略 支持服务级别的亲和性调度,支持跨可用区的高可用和灾难恢复。 微服务监控和弹性伸缩 支持微服务和容器级别的监控,支持微服务的自动伸缩。 推荐搭配使用: 云服务器 ECS + 云数据库 RDS 版 + 对象存储 OSS + 容器服务 负载均衡 混合云架构 统一运维多个云端资源 在容器服务控制台上同时管理云上云下的资源,不需在多种云管理控制台中反复切换。基于容器基础设施无关的特性,使用同一套镜像和编排同时在云上云下部署应用。 能够实现: 在云上伸缩应用 业务高峰期,在云端快速扩容,把一些业务流量引到云端。 云上容灾 业务系统同时部署到云上和云下,云下提供服务,云上容灾。 云下开发测试 云下开发测试后的应用无缝发布到云上。 推荐搭配使用: 云服务器 ECS + 专有网络 VPC + 高速通道(Express Connect) 容器服务 弹性伸缩架构 根据业务流量自动对业务扩容/缩容 容器服务可以根据业务流量自动对业务扩容/缩容,不需要人工干预,避免流量激增扩容不及时导致系统挂掉,以及平时大量闲置资源造成浪费。 能够实现: 快速响应 业务流量达到扩容指标,秒级触发容器扩容操作。 全自动 整个扩容/缩容过程完全自动化,无需人工干预。 低成本 流量降低自动缩容,避免资源浪费。 推荐搭配使用: 云服务器 ECS + 云监控 云监控

1934890530796658 2020-03-26 11:24:27 0 浏览量 回答数 0

问题

容器服务  应用场景

青蛙跳 2019-12-01 21:32:37 467 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

问题

容器服务的应用场景是什么?

反向一觉 2019-12-01 21:17:02 1646 浏览量 回答数 0

问题

MathML 介绍:报错

kun坤 2020-06-08 11:09:17 2 浏览量 回答数 1

问题

比较Apache Hadoop生态系统中不同的文件格式和存储引擎的性能

anrui2016 2019-12-01 22:03:39 2706 浏览量 回答数 0

回答

Go 的优势在于能够将简单的和经过验证的想法结合起来,同时避免了其他语言中出现的许多问题。本文概述了 Go 背后的一些设计原则和工程智慧,作者认为,Go 语言具备的所有这些优点,将共同推动其成为接替 Java 并主导下一代大型软件开发平台的最有力的编程语言候选。很多优秀的编程语言只是在个别领域比较强大,如果将所有因素都纳入考虑,没有其他语言能够像 Go 语言一样“全面开花”,在大型软件工程方面,尤为如此。 基于现实经验 Go 是由经验丰富的软件行业老手一手创建的,长期以来,他们对现有语言的各种缺点有过切身体会的痛苦经历。几十年前,Rob Pike 和 Ken Thompson 在 Unix、C 和 Unicode 的发明中起到了重要作用。Robert Griensemer 在为 JavaScript 和 Java 开发 V8 和 HotSpot 虚拟机之后,在编译器和垃圾收集方面拥有数十年的经验。有太多次,他们不得不等待 Google 规模的 C++/Java 代码库进行编译。于是,他们开始着手创建新的编程语言,将他们半个世纪以来的编写代码所学到的一切经验包含进去。 专注于大型工程 小型工程项目几乎可以用任何编程语言来成功构建。当成千上万的开发人员在数十年的持续时间压力下,在包含数千万行代码的大型代码库上进行协作时,就会发生真正令人痛苦的问题。这样会导致一些问题,如下: 较长的编译时间导致中断开发。代码库由几个人 / 团队 / 部门 / 公司所拥有,混合了不同的编程风格。公司雇佣了数千名工程师、架构师、测试人员、运营专家、审计员、实习生等,他们需要了解代码库,但也具备广泛的编码经验。依赖于许多外部库或运行时,其中一些不再以原始形式存在。在代码库的生命周期中,每行代码平均被重写 10 次,被弄得千疮百痍,而且还会发生技术偏差。文档不完整。 Go 注重减轻这些大型工程的难题,有时会以使小型工程变得更麻烦为代价,例如,代码中到处都需要几行额外的代码行。 注重可维护性 Go 强调尽可能多地将工作转给自动化的代码维护工具中。Go 工具链提供了最常用的功能,如格式化代码和导入、查找符号的定义和用法、简单的重构以及代码异味的识别。由于标准化的代码格式和单一的惯用方式,机器生成的代码更改看起来非常接近 Go 中人为生成的更改并使用类似的模式,从而允许人机之间更加无缝地协作。 保持简单明了 初级程序员为简单的问题创建简单的解决方案。高级程序员为复杂的问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。 ——Charles Connell 让很多人惊讶的一点是,Go 居然不包含他们喜欢的其他语言的概念。Go 确实是一种非常小巧而简单的语言,只包含正交和经过验证的概念的最小选择。这鼓励开发人员用最少的认知开销来编写尽可能简单的代码,以便许多其他人可以理解并使用它。 使事情清晰明了 良好的代码总是显而易见的,避免了那些小聪明、难以理解的语言特性、诡异的控制流和兜圈子。 许多语言都致力提高编写代码的效率。然而,在其生命周期中,人们阅读代码的时间却远远超过最初编写代码所需的时间(100 倍)。例如,审查、理解、调试、更改、重构或重用代码。在查看代码时,往往只能看到并理解其中的一小部分,通常不会有完整的代码库概述。为了解释这一点,Go 将所有内容都明确出来。 错误处理就是一个例子。让异常在各个点中断代码并在调用链上冒泡会更容易。Go 需要手动处理和返回每个错误。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说,这使得错误处理编写起来更加繁琐,但是也更容易理解。 简单易学 Go 是如此的小巧而简单,以至于人们可以在短短几天内就能研究通整个语言及其基本概念。根据我们的经验,培训用不了一个星期(相比于掌握其他语言需要几个月),初学者就能够理解 Go 专家编写的代码,并为之做出贡献。为了方便吸引更多的用户,Go 网站提供了所有必要的教程和深入研究的文章。这些教程在浏览器中运行,允许人们在将 Go 安装到本地计算机上之前就能够学习和使用 Go。 解决之道 Go 强调的是团队之间的合作,而不是个人的自我表达。 在 Go(和 Python)中,所有的语言特性都是相互正交和互补的,通常有一种方法可以做一些事情。如果你想让 10 个 Python 或 Go 程序员来解决同一个问题,你将会得到 10 个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更自在。在查看其他人的代码时,国骂会更少,而且人们的工作可以更好地融合在一起,从而形成了一致的整体,人人都为之感到自豪,并乐于工作。这还避免了大型工程的问题,如: 开发人员认为良好的工作代码很“混乱”,并要求在开始工作之前进行重写,因为他们的思维方式与原作者不同。 不同的团队成员使用不同的语言子集来编写相同代码库的部分内容。 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/e64418f1455d46aaacfdd03fa949f16d.png) 简单、内置的并发性 Go 专为现代多核硬件设计。 目前使用的大多数编程语言(Java、JavaScript、Python、Ruby、C、C++)都是 20 世纪 80 年代到 21 世纪初设计的,当时大多数 CPU 只有一个计算内核。这就是为什么它们本质上是单线程的,并将并行化视为边缘情况的马后炮。通过现成和同步点之类的附加组件来实现,而这些附加组件既麻烦又难以正确使用。第三方库虽然提供了更简单的并发形式,如 Actor 模型,但是总有多个可用选项,结果导致了语言生态系统的碎片化。今天的硬件拥有越来越多的计算内核,软件必须并行化才能高效运行。Go 是在多核处理器时代编写的,并且在语言中内置了简单、高级的 CSP 风格并发性。 面向计算的语言原语 就深层而言,计算机系统接收数据,对其进行处理(通常要经过几个步骤),然后输出结果数据。例如,Web 服务器从客户端接收 HTTP 请求,并将其转换为一系列数据库或后端调用。一旦这些调用返回,它就将接收到的数据转换成 HTML 或 JSON 并将其输出给调用者。Go 的内置语言原语直接支持这种范例: 结构表示数据 读和写代表流式 IO 函数过程数据 goroutines 提供(几乎无限的)并发性 在并行处理步骤之间传输管道数据 因为所有的计算原语都是由语言以直接形式提供的,因此 Go 源代码更直接地表达了服务器执行的操作。 OO — 好的部分 更改基类中的某些内容的副作用 面向对象非常有用。过去几十年来,面向对象的使用富有成效,并让我们了解了它的哪些部分比其他部分能够更好地扩展。Go 在面向对象方面采用了一种全新的方法,并记住了这些知识。它保留了好的部分,如封装、消息传递等。Go 还避免了继承,因为它现在被认为是有害的,并为组合提供了一流的支持。 现代标准库 目前使用的许多编程语言(Java、JavaScript、Python、Ruby)都是在互联网成为当今无处不在的计算平台之前设计的。因此,这些语言的标准库只提供了相对通用的网络支持,而这些网络并没有针对现代互联网进行优化。Go 是十年前创建的,当时互联网已全面发展。Go 的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这就避免了第三方库的常见问题: 碎片化:总是有多个选项实现相同的功能。 膨胀:库常常实现的不仅仅是它们的用途。 依赖地狱:库通常依赖于特定版本的其他库。 未知质量:第三方代码的质量和安全性可能存在问题。 未知支持:第三方库的开发可能随时停止支持。 意外更改:第三方库通常不像标准库那样严格地进行版本控制。 关于这方面更多的信息请参考 Russ Cox 提供的资料 标准化格式 Gofmt 的风格没有人会去喜欢,但人人都会喜欢 gofmt。 ——Rob Pike Gofmt 是一种以标准化方式来格式化 Go 代码的程序。它不是最漂亮的格式化方式,但却是最简单、最不令人生厌的格式化方式。标准化的源代码格式具有惊人的积极影响: 集中讨论重要主题: 它消除了围绕制表符和空格、缩进深度、行长、空行、花括号的位置等一系列争论。 开发人员在彼此的代码库中感觉很自在, 因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式进行格式化代码,但如果其他人按照自己喜欢的方式格式化了代码,这么做很招人烦。 自动代码更改并不会打乱手写代码的格式,例如引入了意外的空白更改。 许多其他语言社区现在正在开发类似 gofmt 的东西。当作为第三方解决方案构建时,通常会有几个相互竞争的格式标准。例如,JavaScript 提供了 Prettier 和 StandardJS。这两者都可以用,也可以只使用其中的一个。但许多 JS 项目并没有采用它们,因为这是一个额外的决策。Go 的格式化程序内置于该语言的标准工具链中,因此只有一个标准,每个人都在使用它。 快速编译 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/8a76f3f07f484266af42781d9e7b8692.png) 对于大型代码库来说,它们长时间的编译是促使 Go 诞生的原因。Google 主要使用的是 C++ 和 Java,与 Haskell、Scala 或 Rust 等更复杂的语言相比,它们的编译速度相对较快。尽管如此,当编译大型代码库时,即使是少量的缓慢也会加剧编译的延迟,从而激怒开发人员,并干扰流程。Go 的设计初衷是为了提高编译效率,因此它的编译器速度非常快,几乎没有编译延迟的现象。这给 Go 开发人员提供了与脚本类语言类似的即时反馈,还有静态类型检查的额外好处。 交叉编译 由于语言运行时非常简单,因此它被移植到许多平台,如 macOS、Linux、Windows、BSD、ARM 等。Go 可以开箱即用地为所有这些平台编译二进制文件。这使得从一台机器进行部署变得很容易。 快速执行 Go 的运行速度接近于 C。与 JITed 语言(Java、JavaScript、Python 等)不同,Go 二进制文件不需要启动或预热的时间,因为它们是作为编译和完全优化的本地代码的形式发布的。Go 的垃圾收集器仅引入微秒量级的可忽略的停顿。除了快速的单核性能外,Go 还可以轻松利用所有的 CPU 内核。 内存占用小 像 JVM、Python 或 Node 这样的运行时不仅仅在运行时加载程序代码,每次运行程序时,它们还会加载大型且高度复杂的基础架构,以进行编译和优化程序。如此一来,它们的启动时间就变慢了,并且还占用了大量内存(数百兆字节)。而 Go 进程的开销更小,因为它们已经完全编译和优化,只需运行即可。Go 还以非常节省内存的方式来存储数据。在内存有限且昂贵的云环境中,以及在开发过程中,这一点非常重要。我们希望在一台机器上能够快速启动整个堆栈,同时将内存留给其他软件。 部署规模小 Go 的二进制文件大小非常简洁。Go 应用程序的 Docker 镜像通常比用 Java 或 Node 编写的等效镜像要小 10 倍,这是因为它无需包含编译器、JIT,以及更少的运行时基础架构的原因。这些特点,在部署大型应用程序时很重要。想象一下,如果要将一个简单的应用程序部署到 100 个生产服务器上会怎么样?如果使用 Node/JVM 时,我们的 Docker 注册表就必须提供 100 个 docker 镜像,每个镜像 200MB,那么一共就需要 20GB。要完成这些部署就需要一些时间。想象一下,如果我们想每天部署 100 次的话,如果使用 Go 服务,那么 Docker 注册表只需提供 10 个 docker 镜像,每个镜像只有 20MB,共只需 2GB 即可。大型 Go 应用程序可以更快、更频繁地部署,从而使得重要更新能够更快地部署到生产环境中。 独立部署 Go 应用程序部署为一个包含所有依赖项的单个可执行文件,并无需安装特定版本的 JVM、Node 或 Python 运行时;也不必将库下载到生产服务器上,更无须对运行 Go 二进制文件的机器进行任何更改。甚至也不需要讲 Go 二进制文件包装到 Docker 来共享他们。你需要做的是,只是将 Go 二进制文件放到服务器上,它就会在那里运行,而不用关心服务器运行的是什么。前面所提到的那些,唯一的例外是使用net和os/user包时针对对glibc的动态链接。 供应依赖关系 Go 有意识避免使用第三方库的中央存储库。Go 应用程序直接链接到相应的 Git 存储库,并将所有相关代码下载(供应)到自己的代码库中。这样做有很多好处: 在使用第三方代码之前,我们可以对其进行审查、分析和测试。该代码就和我们自己的代码一样,是我们应用程序的一部分,应该遵循相同的质量、安全性和可靠性标准。 无需永久访问存储依赖项的各个位置。从任何地方(包括私有 Git repos)获取第三方库,你就能永久拥有它们。 经过验收后,编译代码库无需进一步下载依赖项。 若互联网某处的代码存储库突然提供不同的代码,这也并不足为奇。 即使软件包存储库速度变慢,或托管包不复存在,部署也不会因此中断。 兼容性保证 Go 团队承诺现有的程序将会继续适用于新一代语言。这使得将大型项目升级到最新版本的编译器会非常容易,并且可从它们带来的许多性能和安全性改进中获益。同时,由于 Go 二进制文件包含了它们需要的所有依赖项,因此可以在同一服务器上并行运行使用不同版本的 Go 编译器编译的二进制文件,而无需进行复杂的多个版本的运行时设置或虚拟化。 文档 在大型工程中,文档对于使软件可访问性和可维护性非常重要。与其他特性类似,Go 中的文档简单实用: 由于它是嵌入到源代码中的,因此两者可以同时维护。 它不需要特殊的语法,文档只是普通的源代码注释。 可运行单元测试通常是最好的文档形式。因此 Go 要求将它们嵌入到文档中。 所有的文档实用程序都内置在工具链中,因此每个人都使用它们。 Go linter 需要导出元素的文档,以防止“文档债务”的积累。 商业支持的开源 当商业实体在开放式环境下开发时,那么一些最流行的、经过彻底设计的软件就会出现。这种设置结合了商业软件开发的优势——一致性和精细化,使系统更为健壮、可靠、高效,并具有开放式开发的优势,如来自许多行业的广泛支持,多个大型实体和许多用户的支持,以及即使商业支持停止的长期支持。Go 就是这样发展起来的。 缺点 当然,Go 也并非完美无缺,每种技术选择都是有利有弊。在决定选择 Go 之前,有几个方面需要进行考虑考虑。 未成熟 虽然 Go 的标准库在支持许多新概念(如 HTTP 2 Server push 等)方面处于行业领先地位,但与 JVM 生态系统中的第三方库相比,用于外部 API 的第三方 Go 库可能不那么成熟。 即将到来的改进 由于清楚几乎不可能改变现有的语言元素,Go 团队非常谨慎,只在新特性完全开发出来后才添加新特性。在经历了 10 年的有意稳定阶段之后,Go 团队正在谋划对语言进行一系列更大的改进,作为 Go 2.0 之旅的一部分。 无硬实时 虽然 Go 的垃圾收集器只引入了非常短暂的停顿,但支持硬实时需要没有垃圾收集的技术,例如 Rust。 结语 本文详细介绍了 Go 语言的一些优秀的设计准则,虽然有的准则的好处平常看起来没有那么明显。但当代码库和团队规模增长几个数量级时,这些准则可能会使大型工程项目免于许多痛苦。总的来说,正是这些设计准则让 Go 语言成为了除 Java 之外的编程语言里,用于大型软件开发项目的绝佳选择。

有只黑白猫 2020-01-07 14:11:38 0 浏览量 回答数 0

回答

一、Java内存分配     Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域存储不同类型的数据,这些区域的内存分配和销毁的时间也不同,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范(第2版)》的规定,Java虚拟机管理的内存包括五个运行时数据区域,如下图所示:      1、方法区     方法区(Method Area)是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息(包括类的名称、方法信息、成员变量信息)、常量、静态变量、以及编译器编译后的代码等数据。当方法区无法满足内存分配需求时,将抛出OutOfMemeryError异常。     运行时常量池(Runtime Constant Pool)是方法区的一部分,此区域会在两种情况下存储数据。     (1)class文件的常量池中的数据     class文件中的常量池用于存放编译期生成的各种字面值和常量,这部分内容在类被加载后存放到方法区的运行时常量池中。     字面值:private String name="zhangSan";private int age = 23+3;     常量:private final String TAG = "MainActivity";private final int age = 26;     (2)运行期间生成的常量     运行时常量池相对于class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只能在编译期产生,也就是并非预置入class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。String str = "abc".intern();当运行时常量池中存在字符串"abc时,将该字符串的引用返回,赋值给str,否则创建字符串"abc",加入运行时常量池中,并返回引用赋值给str。既然运行时常量池是方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。 2、虚拟机栈     虚拟机栈是线程私有的内存空间,每个线程都有一个线程栈,每个方法被执行时都会创建一个栈帧,方法执行完成,栈帧弹出,线程运行结束,线程栈被回收。虚拟机栈就是Java中的方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,这个栈帧用于存储局部变量表、操作数栈、指向当前方法所属的类的运行时常量池的引用、方法返回地址等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。局部变量表用来存储方法中的局部变量,包括方法中声明的变量以及函数形参。对于基本数据类型的变量,则直接存储它的值,对于引用类型的变量,则存的是指向对象的引用。局部变量表的大小在编译器就可以确定其大小,并且在程序执行期间局部变量表的大小是不会改变的。程序中的所有计算过程都是在借助于操作数栈来完成的。指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向当前方法所属的类的运行时常量池。方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。     在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。 3、本地方法栈     本地方法栈也是线程私有的内存空间,本地方法栈与Java栈所发挥的作用是非常相似的,它们之间的区别不过是Java栈执行Java方法,本地方法栈执行的是本地方法,有的虚拟机直接把本地方法栈和虚拟机栈合二为一。 4、堆     Java堆是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建,此内存区域的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(TLAB)。Java堆可以处于物理上不连续的内存空间,只要逻辑上连续即可,在实现上,既可以实现固定大小的,也可以是扩展的。如果堆中没有足够的内存分配给实例,并且堆也无法再拓展时,将会抛出OutOfMemeryError异常。     堆是运行时动态分配内存,对象在没有引用变量指向它的时候,才变成垃圾,但是仍然占着内存,在程序空闲的时候(没有工作线程运行,GC线程优先级最低)或者堆内存不足的时候(GC线程被触发),被垃圾回收器释放掉,由于要在运行时动态分配内存,存取速度较慢。 5、程序计数器     程序计数器的作用可以看做是当前线程所执行的字节码的行号指示。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为线程私有的内存。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空。 二、Java内存回收     对于虚拟机栈空间,当方法调用结束后,基本类型变量、引用类型变量、形参占据的空间会被自动释放,但引用类型指向的对象在堆中,堆中的无用内存由垃圾回收线程回收,GC线程优先级最低,只有当没有工作线程存在时GC线程才会执行,或者堆空间不足时会自动触发GC线程工作。除了回收内存,GC线程还负责整理堆中的碎片。 1、四种引用类型     Java中的对象引用分为四种,强引用类型、软引用类型、弱引用类型、虚引用类型。Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。使用软引用和弱引用可以有效的避免oom。软引用关联的对象,只有软引用关联时,才可回收,如果有强引用同时关联,不会回收对象占用的内存,弱引用也如此。 (1)强引用     强引用是使用最普遍的引用,类似Object obj = new Object()、String str = "hello"。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。 (2)软引用(SoftReference)     软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示,如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用通常用于网页缓存、图片缓存,防止内存溢出,在内存充足的时候,缓存对象会一直存在,在内存不足的时候,缓存对象占用的内存会被垃圾收集器回收。使用示例: public void testSoftReference() { Map<String,SoftReference<Bitmap>> imagesCache = new HashMap<String,SoftReference<Bitmap>>(); Bitmap bitmap = getBitmap(); SoftReference<Bitmap> image1 = new SoftReference<Bitmap>(bitmap); imagesCache.put("image1",image1); SoftReference<Bitmap> result_SoftReference = imagesCache.get("image1"); Bitmap result_Bitmap = result_SoftReference .get(); } import java.lang.ref.SoftReference; public class Main { public static void main(String[] args) { SoftReference<String> sr = new SoftReference<String>(new String("hello")); System.out.println(sr.get()); } } (3)弱引用(WeakReference)     弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,在java中用java.lang.ref.WeakReference类来表示。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象,不过由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以用于:单例类持有一个activity引用时,会造成内存泄露,把activity声明为弱引用,在activity销毁后,垃圾收集器扫描到activity对象时,会回收activity对象的内存。使用示例: public class SingleTon1 { private static final SingleTon1 mInstance = null; private WeakReference<Context> mContext; private SingleTon1(WeakReference<Context> context) { mContext = context; } public static SingleTon1 getInstance(WeakReference<Context> context) { if (mInstance == null) { synchronized (SingleTon1.class) { if (mInstance == null) { mInstance = new SingleTon1(context); } } } return mInstance; } } public class MyActivity extents Activity { public void onCreate (Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); SingleTon1 singleTon1 = SingleTon1.getInstance(new WeakReference<Context>(this)); } }import java.lang.ref.WeakReference; public class Main { public static void main(String[] args) { WeakReference<String> sr = new WeakReference<String>(new String("hello")); System.out.println(sr.get()); System.gc(); //通知JVM的gc进行垃圾回收 System.out.println(sr.get()); } } 输出结果: hellonull     第二个输出结果是null,这说明只要JVM进行垃圾回收,被弱引用关联的对象必定会被回收掉。不过要注意的是,这里所说的被弱引用关联的对象是指只有弱引用与之关联,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。 (4)虚引用     虚引用和软引用、弱引用不同,它并不影响对象的生命周期,也无法通过虚引用来取得一个对象实例,在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(ReferenceQueue)联合使用,如下: import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue; public class Main { public static void main(String[] args) { ReferenceQueue<String> queue = new ReferenceQueue<String>(); PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue); System.out.println(pr.get()); } } 2、垃圾回收算法 (1)标记-清除(Mark-Sweep)    标记-清除(Mark-Sweep)算法,分为标记和清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。 标记-清除算法主要问题是:1、效率问题,标记和清除过程的效率很低2、空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集 (2)复制(Copying)算法     复制算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。 复制算法的主要问题是:1、复制算法将内存缩小为原来的一半,过于浪费2、对象存活率较高时就要执行较多的复制操作,造成频繁GC,效率将会变低 (3)标记-整理(Mark-Compact)     标记-整理算法的标记过程仍然与标记-清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,这样连续的内存空间就比较多了。     如上图所示,所有存活的对象依次向左上角移动,(0,4)移动到(0,2),(1,0)移动到(0,3),依次类推,当所有的存活对象移动完成后,把剩余的所有空间清空,也就是清空(1,1)后的所有空间。 (4)分代回收(generational collection) 程序创建的大部分对象的生命周期都很短,只有一小部分对象的生命周期比较长,根据这样的规律,一般把Java堆分为Young Generation(新生代),Old Generation(老年代)和Permanent Generation(持久代),上面几种算法是通过分代回收混合在一起的,这样就可以根据各个年代的特点采用最适当的回收算法。 (1)新生代     在新生代中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to), 这两个区域大小相等,相当于copying算法中的两个区域,它们用来存放每次垃圾回收后存活下来的对象。在新生代中,垃圾回收一般用Copying的算法,速度快。     当新建对象无法放入eden区时,将触发minor collection(minorGC 是清理新生代的GC线程,eden的清理,from、to的清理都由MinorGC完成),将eden区与from区的存活对象复制到to区,经过一次垃圾回收,eden区和from区清空,to区中则紧密的存放着存活对象;当eden区再次满时,minor collection将eden区和to区的存活对象复制到from区,eden区和to区被清空,from区存放eden区和to区的存活对象,就这样from区和to区来回切换。如果进行minor collection的时候,发现to区放不下,则将eden区和from区的部分对象放入成熟代。另一方面,即使to区没有满,JVM依然会移动世代足够久远的对象到成熟代。 (2)成熟代     在成熟代中主要存放应用程序中生命周期长的内存对象,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。如果成熟代放满对象,无法从新生代移入新的对象,那么将触发major collection(major GC清理整合OldGen的内存空间)。 (3)永久代    在永久代中,主要用来放JVM自己的反射对象,比如类对象、方法对象、成员变量对象、构造方法对象等。     此外,垃圾回收一般是在程序空闲的时候(没有工作线程,GC线程优先级较低)或者堆内存不足的时候自动触发,也可以调用System.gc()主动的通知Java虚拟机进行垃圾回收,但这只是个建议,Java虚拟机不一定马上执行,启动时机的选择由JVM决定,并且取决于堆内存中Eden区是否可用 作者:喜六六 来源:CSDN 原文:https://blog.csdn.net/qq_29078329/article/details/78929457 版权声明:本文为博主原创文章,转载请附上博文链接!

auto_answer 2019-12-02 01:50:42 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站