写程序离不开运行时,但是有很多伙伴却并没有搞清楚运行时到底是什么。运行时的概念之所以容易被混淆,是因为运行时有两层不同的含义:run time 和 runtime,先贤们在翻译的时候可能忽略了中间的空格,导致运行时一词代表了两种含义:运行时期和运行环境/系统。
运行时期(Run time)在计算机科学中代表一个程序从开始执行到终止执行的运作时期,与之相对的其他时期包括:设计时期(design time)、编译时期(compile time)、链接时期(link time)与载入时期(load time)。
runtime 是一个通用抽象的术语,指的是计算机程序运行的时候所需要的一切代码库,框架,平台等。它包括了程序的执行环境和执行状态,以及程序在运行时所产生的各种数据和结果。runtime主要是为了实现程序设计语言的执行模型,在每种语言有着不同的实现。runtime的概念在编程中非常重要,它关系到程序的正确性、稳定性和性能等方面。
run time 和 runtime 就有区别又有联系,都是软件设计的基础。run time 是从程序自身的视角来看的,而runtime 则是从程序的执行环境和依赖的视角来看的。因此,在我们讨论运行时的时候,一定要明确上下文,才能理解运行时的真正含义,并通过运行时的相关技术让我们的软件系统更加灵活可靠。
运行时:run time——运行时期
运行时期(run time)是程序生命周期的一个阶段,是代码在执行时的行为。编译时期(compile time)是指程序设计中,编译器在编译源代码时的行为,包括语法分析、语义分析、类型检查、模板实例化、代码生成等。编程语言通常会指出源程序必须满足的编译时期要求。有些编程语言在链接时期或运行时期才执行一部分编译,例如即时编译(Just-in-time compilation)。
程序执行中的某些问题只能在运行时期才能进行检测,例如逻辑错误或数组边界检查等。因此,用户也会遇到诸如运行时错误之类的信息。
运行时期的验证
运行时验证是一种轻量级的验证技术。它是传统验证技术,是模型检测和测试的一个有效补充。它最重要的一个特征是其验证对象为被监控系统的实际运行,从而使得检测到错误时能及时采取相应的调整行为,以达到避免软件失效发生或阻止软件失效进一步传播的目的。
运行时验证关注于检测程序的运行轨迹是否满足或违背监控的性质。当程序的运行满足或违背监控性质时,运行时验证技术一般不会对被监控的系统进行调整。也就是说,运行时验证技术是关于程序运行轨迹是否满足监控性质的判别技术。基于AOP的监控器具有高效(不需要进行环境切换)、容易部署(不涉及到对虚拟机和操作系统的修改)和准确(基于AOP的监控器能够获取被监控程序更多的状态信息)的特点。
程序在编译时期和运行时间的不同体现
这里以多态为例来描述一下程序特性在编译时期和运行时间的不同体现。
先简要澄清一下多态。多态指同一个实体同时具有多种形式,是面向对象程序设计(OOP)的一个重要特征。也就是说,同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不面向对象的。
多态分为两种情况:编译时多态与运行时多态。编译时多态即在编译时就能够确定调用哪个方法。而运行时多态则相反,只有在运行时才能确定调用哪个方法。在方法重载时,都是编译时多态。在编译期可根据参数的数据类型、个数以及次序来确定调用方法。当子类对象引用自身类实例方法时,也为编译时多态。但是当父类对象引用子类实例方法时,是运行时多态,因为此时只有在运行时才可以去匹配到对应方法进行调用。
运行时期的软件配置
运行时期的软件配置是软件配置的一种形式,增加了软件系统的灵活性和适应性。
软件配置可以分为运行时期配置(run time configuration) 和编译时配置 (compile time configuration). 运行时配置是软件的重要接口, 可以定制不同的功能、管理资源的分配、适应环境的变化以及满足不同用户的需求, 主要面向软件管理员和用户, 无需重新编译部署即可实现软件调整. 而编译时配置也称软件生产线配置(software product line configuration, SPL configuration),主要用于软件构建和部署时期决定特定功能模块是否加入可执行程序中, 以此决定软件的最终形态, 主要面向软件开发和部署人员, 必须重新编译才能使用。
运行时期的编译优化
一般地,软件的优化技术分成两类:静态优化和动态优化。其中,动态优化目前主要集中在对动态语言程序如 Java、Ruby、Python 等的优化。运行时期的软件优化大多通过动态编译技术来实现。
动态编译技术又可以分为两大类:①选择性编译:主要关注何时选择程序哪一部分代码进行动态编译和优化;②基于反馈的优化:利用剖析信息来指导动态编译器来做何种级别的编译优化。动态编译器通常支持两种执行方式:一种是解释执行或无优化的编译器编译执行;一种是优化编译,对热点路径进行重点优化。动态编译器中的编译优化工作是在程序运行时期中进行,编译开销包含在程序的运行开销中。
动态编译器不仅可以选择对哪些代码做编译或者优化编译,而且还可以在程序的运行中采集程序的运行信息,主要包括程序的循环深度、程序输入以及运行环境(操作系统、体系结构)等。利用这些运行时信息,动态编译器可以更好地决定采用何种编译优化策略对程序进行编译优化。动态剖析技术使得多级优化编译成为可能,每一级采用特定的优化策略,热点的性
能更容易得到提升,这就是基于反馈的动态优化技术)。
基于反馈的动态优化技术主要通过对程序插桩,利用插入的代码收集需要的程序信息,然后将它们按照一定的格式组织起来进行分析, 从而指导优化器进行重编译。
运行时:runtime——运行时环境/运行时系统
runtime 或者 run-time是指运行环境,又称为“运行时系统”,简称“运行时”,是执行码在目标机器上运行的环境。它有可能是由操作系统提供,或由执行此程序的父程序提供。通常由操作系统负责处理程序的载入:利用加载器(loader)读入程序执行码,进行基本的内存配置,并视需要链接此程序指定的所有动态链接库。有些编程语言也会由此语言提供的运行环境处理上述工作。
运行环境可以解决许多问题,包括应用程序内存的管理、程序如何访问变量、程序之间传递参数的机制、与操作系统的接口等问题。编译器根据具体的运行时系统做出假设,以生成正确的代码。通常情况下,运行时系统将承担一些设置和管理堆栈的责任,并可能包括诸如垃圾回收、线程或其他内置于语言中的动态功能。
对于很多传统高级语言尤其是动态语言而言,运行时系统基本上就是程序和硬件的桥梁。一般地,运行时系统实际上提供了一个动态语言得以执行的统一的虚拟计算机,这样一个虚拟机完全屏蔽了硬件的具体特征从而极大的提高了软件的开发效率。但是正因为这个虚拟机完全屏蔽了程序员接触硬件特性的可能,虚拟机本身必须承担起充分利用硬件特性来高效执行动态语言程序的责任。
运行时模型与运行时体系结构
每种语言都有一个特定的执行模型(Execution Model),而这个执行模型就需要运行时系统的支撑。运行时系统除了提供程序运行机制之外,一般还提供内存管理机制和并发机制。
运行时模型是关联系统的因果关系自述,从问题空间的角度强调系统的结构、行为或目标,运行时模型提供了运行时现象的抽象,利用运行时模型能够修复设计错误或将新的设计决策折叠到正在运行的系统中, 以支持受控的在线设计。同时,运行时模型作为软件演化和适应行为的基础 ,也是解决复杂系统运行时管理问题的关键 。
运行时模型分为运行时结构模型和运行时行为模型。其中, 运行时结构模型侧重于描述系统的组成及配置, 即强调软件的构建方式,如面向对象而言,结构模型描述的是继承关系和调用途径、组件及其连接 等;运行时行为模型侧重于描述组件间动态交互信息,强调根据事件或跟踪流程的系统执行,或者事件的发生及其执行途径,如行为模型描述事件的到达、排队、选择、调度等信息。
运行时软件体系结构是控制运行时系统复杂性、辅助系统运行时管理的有效途径.作为系统运行时刻的动态描述,运行时体系结构刻画了系统当前时刻的构成元素、各元素内部的属性以及元素之间的关系。运行时体系结构与目标系统之间具有“因果关联”,即系统发生变化时,体系结构随之改变;而体系结构被修改后,系统也将随之改变,这种动态的因果关联保证了系统管理者可以通过读写体系结构中的元素、属性以及连接关系,实现对目标系统的监测和调整。运行时体系结构抽象了系统的运行时数据,并以符合管理视角的方式对这些数据进行组织,同时对外提供简单、一致的操作方式.
运行时体系结构与设计阶段体系结构最大的不同在于:运行时体系结构与运行时系统间存在因果联系,而设计阶段体系结构不具备这一属性。运行时体系结构模型侧重如何通过模型来描述运行时系统当前时刻的结构和配置 。
运行时的实现与分类
在编程语言中,runtime通常是由编译器和运行时库共同实现的。编译器负责将源代码编译成可执行代码,而运行时库则负责在程序运行时提供各种运行时支持和服务。运行时库通常包括了各种系统库和标准库,以及一些特定于编程语言的库和框架。
在C语言中,runtime的实现通常是由C库和操作系统共同提供的。C库提供了各种常用的函数和数据类型,而操作系统则提供了一些底层的系统调用和服务。在Java语言中,runtime的实现则是由Java虚拟机(JVM)和Java类库共同提供的。JVM负责将Java字节码编译成可执行代码,并提供各种运行时支持和服务,而Java类库则提供了各种常用的类和函数。
根据运行时系统实现的不同,可以将运行时系统初步分成三类:
第一种是是原生运行时,例如C/C++/Rust,这些语言的运行时系统是依赖操作系统的,操作系统也可以认为是一种“运行时环境”。
第二种是轻运行时,例如Golang,它的运行时是和代码打包到一起的,相对轻量一些。
第三种是重运行时,例如Java(JVM),Python(CPython),还有 C#(.NET Runtime)。它们的运行时环境是需要单独安装的,而且一般还不小,几十兆上百兆都是正常的。
其中,在C/C++里你可以不引用任何库,Rust里有一个专门的特性叫 no_std,脱离标准库提供了一个很牛的能力,就是直接和硬件交互。也就是说,C/C++/Rust是可以用来编写操作系统内核的。
运行时库
运行时库(runtime library),在计算机程序设计领域中,是指编程语言程序运行时(执行)所需要的一种特殊的计算机程序库,编译器会调用运行时库至已编译的可执行二进制代码中。这种库一般包括基本的输入输出或是内存管理等,一般是一群支持正在执行程序的函数,与操作系统合作提供诸如数学运算、输入输出等功能,让开发者不需要“重新发明轮子”,并使用操作系统提供的功能。
运行时库提供了程序执行时的最基本需要。比如Visual Basic需要复杂的运行时库支持而C的运行时库则相对简单。运行时库中的函数可能对程序员透明,也可能不透明,这是由编译器厂商根据语言执行环境的需求而决定的。
许多近代语言设计了更强大的运行时环境并添加了更多功能,很多面向对象语言也包含了分派器与类别读取器,Java虚拟机(JVM)便是此类的典型执行环境,而.NET架构也是另外一个运行时库的实例。异常处理(Exception handling)是专门处理执行期错误的语言机制,使开发者可以完全捕捉非预期错误,或没有适当处理的错误结果。
动态链接库或静态链接库与运行时库的分类角度不同,运行时库就是程序运行的时候所需要依赖的库文件.
C和C++运行时库
为了提高C语言的开发效率,C标准定义了一系列常用的函数,称为C库函数。C标准仅仅定义了函数原型,并没有提供实现。因此这个任务留给了各个支持C语言标准的编译器。每个编译器通常实现了标准C的超集,称为C运行时库(C Run Time Library),简称CRT。C标准库就是任何平台都可以使用的基本C语言库。而CRT除了将C标准库加入所属范围外,还扩展了与平台相关的接口库,这些接口实现根据不同平台调用不同平台的操作系统API。
与C语言类似,C++也定义了自己的标准,同时提供相关支持库,称为C++运行时库或C++标准库。由于C++对C的兼容性,C++标准库包括了C标准库,除此之外还包括了IO流和标准模板库STL。
图片
VC+按照C和C++标准定义的函数原型实现了上述运行时库。为了方便有不同需求的客户使用,VC++分别实现了动态链接库DLL版本和静态链接库LIB版本。同时为了支持程序调试且不影响程序的性能,又分别提供了对应的调试版本。使用DLL版的C和C++运行库,程序在运行时动态的加载对应的DLL。程序体积变小,但一个很大的问题就是一旦找不到对应DLL,程序将无法运行。
在windows上开发多线程程序时,需要选择MT、MTd、MD、MDd其中的一个。对于MT/MTd,由于连接运行时库是LIBCMT.lib/LIBCMTD.lib,这两个库是静态库,所以此种方式编译的程序,移到另一台机器上面也可以正常运行,所以这种方式,不会产生缺少动态库的报错。但是对于MD/MDd,连接的是动态库,所以如果另一台机器上没有MSVCRT.dll/MSVCRTD.dll时,就提示缺少动态库这样的错误。对用户自己写的库或其他第三方库,其连接方式取决于代码(显示连接动态库Loadlibrary)或所提供的lib文件,移动程序到别的机器上时,还是要带上所需要的动态库的。在多工程开发时,最好所有的工程使用同一种运行时库。
运行时安全
近年来出现的运行时应用程序自我保护技术(Runtime Application Self-Protection,简称RASP),是一种解决应用程序漏洞问题并为IT基础架构增加额外安全层的方法。根据Gartner的说法,运行时应用程序自我保护是“建立在或链接到应用程序运行时环境的安全技术,它能够控制应用程序的执行,并且检测和阻止实时攻击。”
运行时应用程序自我保护是预防性的,它可以采取多种措施来阻止黑客破坏系统,在出现问题时控制应用程序。除了检测恶意代码,RASP还可以:
- 突然结束用户会话
- 关闭应用程序或系统
- 标记异常事件的管理员和安全人员
- 向系统用户发送警告
RASP一般与应用程序集成,并通过监视和分析流量以及用户行为来防止程序运行时受到攻击,这使它们可以在应用程序中看到功能级别的代码。这种可见性使其能够更准确地识别攻击,减少误报并报告或阻止构成合法威胁的那些动作。
常见的运行时环境
这里,我们来了解不同编程语言的运行时环境,包括C语言的操作系统运行机制、Apache Portable Runtime、Common Language Runtime、Java Runtime Environment、Android Runtime、iOS Runtime、JavaScript引擎与运行时环境以及小程序的运行时环境。进而,思考各个运行时环境的特点和优劣,以及它们在不同平台上的表现。
C/C++运行时
C 语言最主要的运行时,实际上就是操作系统。C 语言和现代的各种操作系统可以说是伴生关系,就像 Java 和 JVM 是伴生关系一样。
在程序执行机制方面,C 语言编译完毕的程序是完全按照操作系统的运行机制来执行的。在内存管理方面,C 语言使用了操作系统提供的线程栈,操作系统能够自动帮助程序管理内存。程序也可以从堆里申请内存,但必须自己负责释放,没有自动内存管理机制。在并发机制方面,当然也是直接用操作系统提供的线程机制。如果操作系统没有提供协程和 Actor 机制,所以 C 语言也没有提供这种并发机制。
APR
Apache可移植运行时(Apache Portable Runtime,简称APR)是Apache HTTP服务器的支持库,提供了一组映射到下层操作系统的API。如果操作系统不支持某个特定的功能,APR将提供一个模拟实现。这样程序员使用APR编写真正可在不同平台上移植的程序。
APR使得平台细节的处理进行下移。对于应用程序而言,它们根本就不需要考虑具体的平台,不管是Unix、Linux还是Window,应用程序执行的接口基本都是统一一致的。因此对于APR而言,可移植性和统一的上层接口是其考虑的一个重点。而最初,APR是作为Apache HTTP服务器的一部分而存在的,但是Apache软件基金会将其延伸成一个单独的项目,其他的应用程序可以使用APR来实现平台无关性。APR的目标则是希望安全合并所有的能够合并的代码而不需要牺牲性能。
CLR
通用语言执行平台(Common Language Runtime,简称CLR)是微软为他们的.NET的虚拟机所选用的名称。它是微软对通用语言架构(CLI)的实例,它定义了一个程式码执行的环境。CLR执行一种称为通用中间语言的字节码,运行在Windows操作系统上。
.NET 运行时安装在计算机上,供依赖该框架的应用程序使用。该运行时具有一个广泛的标准类库集,称为运行时框架库或基类库 (BCL)。此外,还有运行时库的扩展,这些库为许多常见和特定于与应用的类型、算法和实用程序功能提供实现。
JRE
JRE 是 Java 程序的运行环境,其中包含一个 JAVA 虚拟机以及一些标准的函数类库。也就是说,JRE(Java Runtime Environment)一种能够执行Java字节码的虚拟机,以堆栈结构来实现的。JVM有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JRE屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的字节码,就可以在多种平台上不加修改地运行。
作为一种编程语言的虚拟机,JVM实际上不只是专用于Java语言,只要生成的编译文件符合JVM对载入编译文件格式要求,任何语言都可以在JRE上运行。
ART
Android Runtime(缩写为ART),是一种在Android操作系统上的运行环境,由Google公司研发,并在2013年作为Android 4.4系统中的一项测试功能正式对外发布,在Android 5.0及后续Android版本中作为正式的运行时库取代了以往的Dalvik虚拟机。ART能够把应用程序的字节码转换为机器码,是Android所使用的一种新的虚拟机。
图片
与Dalvik虚拟机不同的是,ART引入了AOT这种预编译技术,在应用程序安装的过程中,ART就已经将所有的字节码重新编译成了机器码。应用程序运行过程中无需进行实时的编译工作,只需要进行直接调用。因此,ART极大地提高了应用程序的运行效率,同时也减少了手机的电量消耗,提高了移动设备的续航能力,在垃圾回收等机制上也有了较大的提升。为了保证向下兼容,ART使用了相同的Dalvik字节码文件(dex),即在应用程序目录下保留了dex文件供旧程序调用,然而.odex文件则替换成了可执行与可链接格式(ELF)可执行文件。一旦一个程序被ART的dex2oat命令编译,那么这个程序将会只通过ELF可执行文件来运行。因此,相对于Dalvik虚拟机模式,ART模式下Android应用程序的安装需要消耗更多的时间,同时也会占用更大的内部储存空间,用于储存编译后的代码,但节省了很多Dalvik虚拟机用于实时编译的时间。
iOS Runtime
在iOS中,通常将 Runtime 理解成实现Obj-C语言动态的 API。Obj-C的动态性就是运行时机制,其中最主要的是消息机制。
在iOS Runtime的支持下,动态类型和动态绑定使得选择那个接收者以及调用哪个方法都可以在运行时决定;应用可以根据需要加载可执行代码以及资源,而不是在启动时就加载所有资源;iOS在编译的时候会根据方法的名字(包括参数序列),生成一个用来区分这个方法的唯一的ID,这个ID是SEL类型的,只要方法的名字(包括参数序列)相同,那么它们的ID都是相同的。通过 dlopen 把动态库文件载入运行的 App 里,接下来 dlsym 会得到动态库的符号地址,然后就可以处理类的替换工作。整个过程无需重新编译和重载 App,使用动态库方式极速调试的目的就达成了。
JS引擎与运行时
JavaScript 引擎是一个解释 JavaScript 代码的程序,该引擎负责执行代码。任何 JavaScript 引擎通常都包含一个调用栈和一个堆。调用栈是代码执行的地方,堆是一个非结构化的内存池,用于存储应用程序所需的所有对象。当代码片段进入运行时环境时,代码首先被读取,随后被解析为叫作抽象语法树(AST)的数据结构。生成的树被用来来创建机器代码。
JavaScript 运行时环境包含了运行 JavaScript 所需的所有组件,包括 JavaScript 引擎、Web API 和回调队列。
图片
浏览器运行时和 Node.js 是JS运行时环境的具体例子。当 JavaScript 在 Web 浏览器中执行时,它是在浏览器的运行时环境中运行的。浏览器运行时环境提供对 DOM 的访问,从而实现了与网页元素的交互,处理事件,以及对页面结构的操作。Node.js 提供了一个服务器端运行时环境,它在浏览器外部执行 JavaScript,所以它不能访问 Web API。Node.js 运行时环境将其替换为叫作 C++ 绑定和线程池的东西。每个主流的浏览器都有一个可以执行 JavaScript 代码的 JavaScript 引擎。最流行的是谷歌浏览器 Chrome 的 V8 引擎,同时为 Chrome 和 Node.js 提供了支持。
小程序的运行时
小程序的运行时环境可以看作JS运行时环境的特例。不同运行平台上,小程序的运行时环境有所不同,性能表现也存在差异:
- 在 iOS、iPadOS 和 Mac OS 上,小程序的 JavaScript 代码运行在 JavaScriptCore 中,;
- 在 Android 上,小程序的 JavaScript 代码运行在 V8 中;
- 在 Windows 上,小程序JavaScript 使用 Chromium 内核;
- 在 开发工具上,小程序 JavaScript 代码一般运行在 NW.js 中。
其中,JavaScriptCore 无法开启 JIT 编译,同等条件下的运行性能要明显低于其他平台。
尽管各运行环境是十分相似的,但是还是有些许区别,那就是JavaScript 语法和 API 支持存在不一致,开发者可以通过开启 ES6 转 ES5 的功能来规避。
运行时的云应用
容器运行时负责运行容器并设置命名空间和控制组,如Docker、containerd、rkt、Kata Container、CRI-O等;FaaS的运行时支持多种语言,每个主要编程语言版本都有单独的运行时,可以使用Lambda提供的运行时或构建自己的运行时,也可以自定义运行时为Shell脚本或可在Linux可执行的二进制文件。
容器运行时
容器运行时更侧重于运行容器,为容器设置命名空间和控制组(cgroup),也被称为底层容器运行时。高层的容器运行时或容器引擎专注于格式、解包、管理和镜像共享。它们还为开发者提供 API,这种情况下的容器运行时相当于一个可独立运行的模块,可以将它视为功能性的 Native 类库使用。
Docker是目前最广泛的容器引擎技术。当然,随着容器生态圈的日益繁荣,业界慢慢也出现了其他各种运行时工具,如containerd、rkt、Kata Container、CRI-O等。这些工具提供的功能不尽相同,有些只有容器运行的功能,有些除运行容器外还提供了容器镜像的管理功能。
图片
低层运行时主要负责与宿主机操作系统打交道,根据指定的容器镜像在宿主机上运行容器的进程,并对容器的整个生命周期进行管理。常见的低层运行时系统的种类有:
- runc:传统的运行时环境,基于Linux Namespace和Cgroups技术实现,代表实现Docker
- runv:基于虚拟机管理程序的运行时环境,通过虚拟化 guest kernel,将容器和主机隔离开来,使得其边界更加清晰,代表实现是Kata Container和Firecracker
- runsc:runc + safety ,通过拦截应用程序的所有系统调用,提供安全隔离的轻量级容器运行时沙箱,代表实现是谷歌的gVisor
Kubernetes利用Docker作为容器运行时管理工具,后来又添加了对rkt的支持。但随着容器技术的蓬勃发展,越来越多的运行时工具出现,提供对所有运行时工具的支持,显然是一项庞大的工程。如果直接将运行时的集成内置于Kubernetes,对Kubernetes代码本身也是一种负担,每次更新,都需要考虑对所有容器运行时的兼容适配。因此,Kubernetes将对容器的操作抽象为一个接口,将此接口作为kubelet与运行时工具之间的桥梁,kubelet通过发送接口请求对容器进行启动和管理,各个容器工具通过实现这个接口即可接入Kubernetes。这个统一的容器操作接口,就是容器运行时接口(Container Runtime Interface, CRI)。
FaaS的运行时
Lambda 通过使用运行时支持多种语言。运行时系统提供特定于语言的环境,用于在 Lambda 与函数之间中继调用事件、上下文信息和响应。我们可以使用 Lambda 提供的运行时,或构建您自己的运行时。
每个主要编程语言版本都有单独的运行时,并具有唯一的运行时标识符,例如 python3.10 或 nodejs18.x。要将某个云端的函数计算配置为使用新的主要语言版本,需要更改运行时系统标识符。对于定义为容器映像的函数,可以在创建容器映像时选择运行时系统和 Linux 发行版。要更改运行时,需要创建一个新的容器映像。
在将 .zip 文件存档作为部署程序包的时候,需要在创建函数时选择运行时。要更改运行时,需要更新云端函数计算的配置。云服务的底层执行环境提供了可通过函数代码访问的额外的库和环境变量。
自定义的运行时可以是Shell脚本,也可以是可在linux可执行的二进制文件。
小结
本文首先澄清了运行时的核心概念,然后介绍了不同类型的运行时环境,包括Android的ART和Dalvik虚拟机、iOS的Runtime、JavaScript引擎和运行时环境、小程序的运行时环境、以及云应用的容器运行时和FaaS的运行时。对于容器运行时,了解了常见的低层运行时种类以及Kubernetes如何通过容器运行时接口(CRI)实现对所有容器运行时的支持。对于FaaS的运行时,介绍了Lambda如何通过使用运行时支持多种语言,并提供特定于语言的环境,用于在Lambda与函数之间中继调用事件、上下文信息和响应。