查看源代码 code (内核 v10.2)

Erlang 代码服务器进程的接口。

此模块包含 Erlang _代码服务器_ 的接口,该服务器负责将编译后的代码加载到正在运行的 Erlang 运行时系统中。

运行时系统可以在_交互式_或_嵌入式_模式下启动。具体使用哪种模式由命令行标志 -mode 决定

% erl -mode embedded

模式如下:

  • 在_交互式_模式(默认模式)下,只有运行时系统所需的模块在系统启动期间加载。其他代码在首次引用时动态加载。当调用某个模块中的函数时,如果该模块尚未加载,代码服务器会搜索并尝试加载该模块。

  • 在_嵌入式_模式下,模块不会自动加载。尝试使用尚未加载的模块会导致错误。当启动脚本加载所有模块时(如在 OTP 发布版本中通常所做的那样),建议使用此模式。(仍然可以通过显式命令代码服务器来加载代码)。

为了防止意外重新加载影响 Erlang 运行时系统的模块,目录 kernelstdlibcompiler 被认为是_粘性的_。这意味着如果用户尝试重新加载驻留在其中任何一个目录中的模块,系统会发出警告并拒绝该请求。可以使用命令行标志 -nostick 禁用此功能。

代码路径

在交互模式下,代码服务器维护一个_代码路径_,其中包含一个目录列表,在尝试加载模块时,它会按顺序搜索这些目录。

最初,代码路径由当前工作目录和库目录 $OTPROOT/lib 下的所有 Erlang 目标代码目录组成,其中 $OTPROOT 是 Erlang/OTP 的安装目录,即 code:root_dir()。目录可以命名为 Name[-Vsn],并且默认情况下,代码服务器会在具有相同 Name 的目录中选择版本号最高的目录。后缀 -Vsn 是可选的。如果 Name[-Vsn] 下存在 ebin 目录,则将此目录添加到代码路径。

可以使用环境变量 ERL_LIBS(在操作系统中定义)来定义更多库目录,这些目录的处理方式与上面描述的标准 OTP 库目录相同,但没有 ebin 目录的目录将被忽略。

在额外的目录中找到的所有应用程序目录都会出现在标准 OTP 应用程序之前,但 Kernel 和 STDLIB 应用程序除外,它们会放置在任何额外的应用程序之前。换句话说,在任何额外的库目录中找到的模块会覆盖 OTP 中同名的模块,但 Kernel 和 STDLIB 中的模块除外。

环境变量 ERL_LIBS(如果已定义)应包含一个以冒号分隔(对于类 Unix 系统)或以分号分隔(对于 Windows)的附加库列表。

示例

在类 Unix 系统上,可以将 ERL_LIBS 设置为以下值:

/usr/local/jungerl:/home/some_user/my_erlang_lib

$OTPROOTERL_LIBS 和启动脚本指定的代码路径默认情况下会缓存它们的列表(除了 ".")。代码服务器将查找其目录中的内容一次,并避免将来遍历文件系统。因此,在 Erlang VM 启动后添加到此类目录中的模块将不会被选取。可以通过设置 -cache_boot_paths false 或调用 code:set_path(code:get_path()) 来禁用此行为。

更改

在 Erlang/OTP 26 中添加了对缓存代码路径中目录的支持。

默认情况下,命令行选项 -pa-pz 给出的目录不会被缓存。许多操作代码路径的函数接受 cache 原子作为可选参数,以选择性地启用缓存。

从归档文件加载代码

更改

对归档文件的现有实验性支持将在未来版本中更改。截至 Erlang/OTP 27,函数 code:lib_dir/2-code_path_choice 标志以及使用 erl_prim_loader 从归档文件中读取文件已被弃用。

使用归档文件的 escript 脚本应该使用 escript:extract/2 从其归档文件中读取数据文件,而不是使用 code:lib_dir/2erl_prim_loader

Erlang 归档文件是扩展名为 .ezZIP 文件。Erlang 归档文件也可以 包含在 escript 文件中,其文件扩展名是任意的。

Erlang 归档文件可以包含整个 Erlang 应用程序或应用程序的一部分。归档文件中的结构与应用程序的目录结构相同。例如,如果要创建 mnesia-4.4.7 的归档文件,则该归档文件必须命名为 mnesia-4.4.7.ez,并且必须包含一个名为 mnesia-4.4.7 的顶层目录。如果名称中省略了版本部分,则在归档文件中也必须省略。也就是说,mnesia.ez 归档文件必须包含一个 mnesia 顶层目录。

例如,可以像这样创建一个应用程序的归档文件:

zip:create("mnesia-4.4.7.ez",
	["mnesia-4.4.7"],
	[{cwd, code:lib_dir()},
	 {compress, all},
	 {uncompress,[".beam",".app"]}]).

归档文件中的任何文件都可以压缩,但是为了加快对频繁读取文件的访问速度,最好将 beamapp 文件以未压缩的形式存储在归档文件中。

通常,应用程序的顶层目录位于库目录 $OTPROOT/lib 中或由环境变量 ERL_LIBS 引用的目录中。在启动时,当计算初始代码路径时,代码服务器还会查找这些目录中的归档文件,并可能将归档文件中的 ebin 目录添加到代码路径。然后,代码路径包含的目录路径类似于 $OTPROOT/lib/mnesia.ez/mnesia/ebin$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin

代码服务器使用 ERTS 中的模块 erl_prim_loader(可能通过 erl_boot_server)从归档文件中读取代码文件。但是,erl_prim_loader 中的函数也可以由其他应用程序用于从归档文件中读取文件。例如,调用 erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)" 将列出归档文件内部目录的内容。请参阅 erl_prim_loader

应用程序归档文件和常规应用程序目录可以共存。当需要将应用程序的某些部分作为常规文件时,这可能很有用。一个典型的例子是 priv 目录,它必须作为常规目录驻留,才能动态链接驱动程序并启动端口程序。对于其他不需要此功能的应用程序,priv 目录可以驻留在归档文件中,并且可以通过 erl_prim_loader 读取 priv 目录下的文件。

当目录添加到代码路径以及(重新)设置整个代码路径时,代码服务器会决定从归档文件中读取应用程序中的哪些子目录,以及作为常规文件读取哪些子目录。如果之后添加或删除了目录,则如果未更新代码路径(可能与之前的路径相同,以触发目录解析更新),则文件访问可能会失败。

对于应用程序归档文件中的第二级目录(ebinprivsrc 等),代码服务器首先选择存在的常规目录,然后选择归档文件中的目录。函数 code:lib_dir/2 返回子目录的路径。例如,code:lib_dir(megaco, ebin) 可以返回 /otp/root/lib/megaco-3.9.1.1.ez/megaco-3.9.1.1/ebin,而 code:lib_dir(megaco, priv) 可以返回 /otp/root/lib/megaco-3.9.1.1/priv

escript 文件包含归档文件时,对 escript 的名称没有限制,对可以在嵌入式归档文件中存储的应用程序数量也没有限制。单个 Beam 文件也可以驻留在归档文件的顶层。在启动时,嵌入式归档文件中的顶层目录和所有(第二级)ebin 目录都将添加到代码路径。请参阅 escript

escript 脚本从归档文件中读取数据文件的未来安全方式是使用 escript:extract/2 函数。

当代码路径中目录的选择为 strict 时(在 Erlang/OTP 27 中是默认值),最终进入代码路径的目录正是声明的目录。这意味着,例如,如果将目录 $OTPROOT/lib/mnesia-4.4.7/ebin 显式添加到代码路径中,则代码服务器不会从 $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin 加载文件。

可以通过命令行标志 -code_path_choice Choice 控制此行为。如果该标志设置为 relaxed,则代码服务器会根据实际文件结构选择合适的目录。如果存在常规应用程序 ebin 目录,则会选择该目录。否则,如果存在归档文件中的 ebin 目录,则会选择该目录。如果它们都不存在,则会选择原始目录。

命令行标志 -code_path_choice Choice 还会影响模块 init 如何解释 boot script。对 boot script 中显式代码路径的解释可以是 strictrelaxed。当在不编辑 boot script 的情况下详细说明从归档文件加载代码时,将该标志设置为 relaxed 尤其有用。默认值已在 OTP 27 中更改为 strict,并且该选项计划在 OTP 28 中删除。请参阅 Erts 应用程序中的模块 init

当前代码和旧代码

一个模块的代码在系统中可以存在两种变体:当前代码旧代码。当一个模块首次加载到系统中时,模块代码将变为当前代码,并且全局导出表会更新为指向该模块导出的所有函数的引用。

当加载该模块的新实例时,前一个实例的代码将变为旧代码,并且所有引用前一个实例的导出条目都会被删除。之后,新实例会像第一次加载一样被加载,并变为当前代码。

模块的旧代码和当前代码都是有效的,甚至可以并发执行。区别在于旧代码中的导出函数不可用。因此,不能对旧代码中的导出函数进行全局调用,但由于进程仍然存在于其中,旧代码仍然可以执行。

如果加载了模块的第三个实例,代码服务器会删除(清除)旧代码,并且其中存在的任何进程都会被终止。然后,第三个实例将变为当前代码,而之前当前的代码将变为旧代码。

有关旧代码和当前代码的更多信息,以及如何使进程从旧代码切换到当前代码,请参阅《Erlang 参考手册》中的“编译和代码加载”部分:Erlang 参考手册

原生覆盖率支持

在使用 JIT 的运行时系统中,原生覆盖率是一种轻量级方法,用于找出哪些函数或行已被执行,或者每个函数或行已被执行了多少次。

更改

对原生覆盖率的支持是在 Erlang/OTP 27 中添加的。

原生覆盖率通过在加载时对代码进行检测来工作。当一个模块已经为原生覆盖率收集进行了检测时,除了重新加载该模块外,以后无法禁用覆盖率收集。但是,保持覆盖率收集运行的开销通常可以忽略不计,特别是对于只跟踪哪些函数已被执行的覆盖率模式 function

如果运行时系统支持,Tools 应用程序中的 cover 工具将自动使用原生覆盖率支持。

仅当 cover 不足时,才需要使用接下来描述的功能,例如:

  • 如果想要收集运行时系统启动时运行的代码的覆盖率信息(模块 init 等)。 cover 只能在 Erlang 系统启动后使用,并且它将重新加载要分析的每个模块。

  • 如果需要以对测试系统造成绝对最小干扰的方式收集覆盖率信息。 cover 始终计算每行执行的次数(覆盖率模式 line_counters),但通过使用原生覆盖率,可以使用开销较小的覆盖率模式,例如 function,其开销几乎可以忽略不计。

使用原生覆盖率的简短摘要

如果要使用 lineline_counters 覆盖率模式,则必须使用选项 line_coverage 编译要测试的代码。

使用 set_coverage_mode(Mode) 为随后加载的所有代码设置覆盖率模式,或者使用 erl 的选项 +JPcover 设置。

可以选择通过调用 reset_coverage(Module) 重置要测试的所有模块的覆盖率信息。

运行要收集其覆盖率信息的代码。

通过调用 get_coverage(Level, Module) 读取所有感兴趣模块的计数器,其中 Levelfunctionline

其他原生覆盖率 BIF

以下 BIF 有时很有用,例如,当运行时系统不支持原生覆盖率时可以优雅地失败:

参数类型和无效参数

模块和应用程序名称是原子,而文件和目录名称是字符串。出于向后兼容的原因,某些函数接受字符串和原子,但未来版本可能只允许记录在案的参数。

如果传递了错误的类型(例如,期望原子的地方传递了整数或元组),则此模块中的函数通常会引发异常。如果参数类型正确,但存在其他错误(例如,set_path/1 指定了不存在的目录),则会返回错误元组。

代码加载函数的错误原因

加载代码的函数(例如 load_file/1)如果加载操作失败,则返回 {error,Reason}。以下是对常见原因的描述。

  • badfile - 对象代码格式不正确,或者对象代码中的模块名称不是预期的模块名称。

  • nofile - 未找到包含对象代码的文件。

  • not_purged - 由于已经存在代码的旧版本,因此无法加载对象代码。

  • on_load_failure - 模块有一个 -on_load 函数,当调用该函数时失败。

  • sticky_directory - 对象代码驻留在粘性目录中。

摘要

函数

Dir 添加到代码路径的开头。

遍历 Dirs 并将每个 Dir 添加到代码路径的开头。

Dirs 中的目录添加到代码路径的末尾。

Dir 作为代码路径中最后一个目录添加。

返回所有可用模块的元组列表 {Module, Filename, Loaded}

返回所有已加载模块的元组列表 {Module, Loaded}

尝试以原子方式加载列表 Modules 中的所有模块。

在代码路径中的所有目录中搜索具有相同名称的模块名称,并将报告写入 stdout

清除代码路径缓存。

返回编译器库目录。

如果系统支持覆盖率,则返回 true,否则返回 false

从代码路径中删除一个目录。

从代码路径中删除目录。

删除 Module 的当前代码,即 Module 的当前代码将变为旧代码。

尝试以与 load_file/1 相同的方式加载模块,除非该模块已经加载。

尝试以与 load_file/1 相同的方式加载列表 Modules 中尚未加载的任何模块。

尝试加载先前由 prepare_loading/1 准备的所有模块的代码。

返回模块 Modulefunctionline 覆盖率数据。

返回由 erl 的选项 +JPcoverset_coverage_mode/1 设置的覆盖率模式。

获取给定模块的覆盖率模式。

如果可用,则返回 ModuleEEP 48 样式文档。

返回一个原子,描述代码服务器的模式:interactiveembedded

如果代码路径中找到,则返回模块 Module 的对象代码。

返回代码路径。

检查是否已加载 Module

如果 Module 是从粘性目录加载的模块的名称(换句话说:尝试重新加载模块将失败),则返回 true;如果 Module 不是已加载的模块或不是粘性的,则返回 false

返回库目录,$OTPROOT/lib,其中 $OTPROOT 是 Erlang/OTP 的根目录。

返回应用程序 Name库目录(顶层目录)的路径,该应用程序位于 $OTPROOT/lib 下或环境变量 ERL_LIBS 引用的目录中。

返回应用程序顶层目录下的子目录的路径。

等效于 load_file(Module),不同之处在于 Filename 是绝对或相对文件名。

从二进制文件加载对象代码。

尝试使用代码路径加载 Erlang 模块 Module

返回 module_status/1 返回 modified 的所有当前已加载模块的列表。

有关详细信息,请参阅 module_status/1all_loaded/0

返回 Module 相对于磁盘上对象文件的状态。

返回与所使用的 Erlang 机器相对应的对象代码文件扩展名。

准备加载列表 Modules 中的模块。

返回应用程序中 priv 目录的路径。

清除 Module 的代码,即删除标记为旧的代码。

将代码路径中旧的目录 .../Name[-Vsn][/ebin] 替换为 Dir

重置模块 Module 的覆盖率信息。

返回 Erlang/OTP 的根目录,即安装目录。

为后续加载的模块设置覆盖率模式,类似于 erl 的选项 +JPcover

将代码路径设置为目录列表 Path

清除 Module 的代码,即删除标记为旧的代码,但前提是没有进程仍在其中运行。

Dir 标记为粘性目录。

取消标记为粘性目录的目录。

在代码路径中搜索 Filename,这是一个任意类型的文件。

如果模块未加载,此函数将在代码路径中搜索包含 Module 对象代码的第一个文件,并返回绝对文件名。

类型

此类型的链接

add_path_ret()

查看源代码 (未导出)
-type add_path_ret() :: true | {error, bad_directory}.
-type cache() :: cache | nocache.
-type coverage_mode() :: none | function | function_counters | line_coverage | line_counters.
-type load_error_rsn() :: badfile | nofile | not_purged | on_load_failure | sticky_directory.
-type load_ret() :: {error, What :: load_error_rsn()} | {module, Module :: module()}.
此类型的链接

loaded_filename()

查看源代码 (未导出)
-type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms().
此类型的链接

loaded_ret_atoms()

查看源代码 (未导出)
-type loaded_ret_atoms() :: cover_compiled | preloaded.
-type module_status() :: not_loaded | loaded | modified | removed.
-opaque prepared_code()

一个持有准备好的代码的不透明术语。

此类型的链接

replace_path_ret()

查看源代码 (未导出)
-type replace_path_ret() :: true | {error, bad_directory | bad_name | {badarg, _}}.
此类型的链接

set_path_ret()

查看源代码 (未导出)
-type set_path_ret() :: true | {error, bad_directory}.

函数

-spec add_path(Dir) -> add_path_ret() when Dir :: file:filename().

等效于 add_pathz(Dir, nocache)

此函数的链接

add_path(Dir, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_path(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

等效于 add_pathz(Dir, Cache)

-spec add_patha(Dir) -> add_path_ret() when Dir :: file:filename().

等效于 add_patha(Dir, nocache)

此函数的链接

add_patha(Dir, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_patha(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

Dir 添加到代码路径的开头。

如果 Dir 存在,则会将其从代码路径中的旧位置删除。

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

如果成功,则返回 true;如果 Dir 不是目录名称,则返回 {error, bad_directory}

-spec add_paths(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

等效于 add_pathsz(Dirs, nocache)

此函数的链接

add_paths(Dirs, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_paths(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

等效于 add_pathsz(Dirs, Cache)

-spec add_pathsa(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

等效于 add_pathsa(Dirs, nocache)

此函数的链接

add_pathsa(Dirs, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_pathsa(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

遍历 Dirs 并将每个 Dir 添加到代码路径的开头。

这意味着 Dirs 的顺序在生成的代码路径中是相反的。例如,如果 Dirs[Dir1,Dir2],则生成的路径将是 [Dir2,Dir1|OldCodePath]

如果代码路径中已存在 Dir,则会将其从旧位置删除。

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

始终返回 ok,无论每个单独的 Dir 是否有效。

-spec add_pathsz(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

等效于 add_pathsz(Dirs, nocache)

此函数的链接

add_pathsz(Dirs, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_pathsz(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

Dirs 中的目录添加到代码路径的末尾。

不会添加代码路径中已存在的目录。

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

始终返回 ok,无论每个单独的 Dir 是否有效。

-spec add_pathz(Dir) -> add_path_ret() when Dir :: file:filename().

等效于 add_pathz(Dir, nocache)

此函数的链接

add_pathz(Dir, Cache)

查看源代码 (自 OTP 26.0 起)
-spec add_pathz(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

Dir 作为代码路径中最后一个目录添加。

如果 Dir 已经存在于路径中,则不会添加。

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

如果成功,则返回 true;如果 Dir 不是目录名称,则返回 {error, bad_directory}

此函数的链接

all_available()

查看源代码 (自 OTP 23.0 起)
-spec all_available() -> [{Module, Filename, Loaded}]
                       when Module :: string(), Filename :: loaded_filename(), Loaded :: boolean().

返回所有可用模块的元组列表 {Module, Filename, Loaded}

如果模块已加载或在调用时会被加载,则认为该模块可用。Filename 通常是绝对文件名,如 is_loaded/1 中所述。

-spec all_loaded() -> [{Module, Loaded}] when Module :: module(), Loaded :: loaded_filename().

返回所有已加载模块的元组列表 {Module, Loaded}

Loaded 通常是绝对文件名,如 is_loaded/1 中所述。

此函数的链接

atomic_load(Modules)

查看源代码 (自 OTP 19.0 起)
-spec atomic_load(Modules) -> ok | {error, [{Module, What}]}
                     when
                         Modules :: [Module | {Module, Filename, Binary}],
                         Module :: module(),
                         Filename :: file:filename(),
                         Binary :: binary(),
                         What ::
                             badfile | nofile | on_load_not_allowed | duplicated | not_purged |
                             sticky_directory | pending_on_load.

尝试以原子方式加载列表 Modules 中的所有模块。

这意味着要么所有模块同时加载,要么如果任何模块出现问题,则不加载任何模块。

加载失败的原因如下:

  • badfile - 对象代码格式不正确,或者对象代码中的模块名称不是预期的模块名称。

  • nofile - 不存在包含对象代码的文件。

  • on_load_not_allowed - 模块包含一个 -on_load 函数

  • duplicated - 模块在 Modules 中被多次包含。

  • not_purged - 无法加载对象代码,因为该代码的旧版本已经存在。

  • sticky_directory - 对象代码驻留在粘性目录中。

  • pending_on_load - 先前加载的模块包含一个从未完成的 -on_load 函数。

如果需要在更改代码时尽量减少应用程序不活动的时间,请使用 prepare_loading/1finish_loading/1 而不是 atomic_load/1。 这是一个例子:

{ok,Prepared} = code:prepare_loading(Modules),
%% Put the application into an inactive state or do any
%% other preparation needed before changing the code.
ok = code:finish_loading(Prepared),
%% Resume the application.
-spec clash() -> ok.

在代码路径中的所有目录中搜索具有相同名称的模块名称,并将报告写入 stdout

此函数的链接

clear_cache()

查看源代码 (自 OTP 26.0 起)
-spec clear_cache() -> ok.

清除代码路径缓存。

如果目录被缓存,它的缓存将被清除一次,然后在未来遍历中会重新计算并再次缓存。

要清除单个路径的缓存,请将其重新添加到代码路径(使用 add_path/2)或替换它(使用 replace_path/3)。要禁用所有缓存,请使用 code:set_path(code:get_path()) 重置代码路径。

始终返回 ok

-spec compiler_dir() -> file:filename().

返回编译器库目录。

等同于 code:lib_dir(compiler)

此函数的链接

coverage_support()

查看源代码 (自 OTP 27.0 起)
-spec coverage_support() -> Supported when Supported :: boolean().

如果系统支持覆盖率,则返回 true,否则返回 false

另请参阅: 原生覆盖率支持

-spec del_path(NameOrDir) -> boolean() | {error, What}
                  when NameOrDir :: Name | Dir, Name :: atom(), Dir :: file:filename(), What :: bad_name.

从代码路径中删除一个目录。

该参数可以是一个原子 Name,在这种情况下,代码路径中名为 .../Name[-Vsn][/ebin] 的目录将被删除。此外,还可以将完整的目录名称 Dir 指定为参数。

返回:

  • true - 如果成功

  • false - 如果未找到该目录

  • {error, bad_name} - 如果参数无效

此函数的链接

del_paths(NamesOrDirs)

查看源代码 (自 OTP 26.0 起)
-spec del_paths(NamesOrDirs) -> ok
                   when NamesOrDirs :: [Name | Dir], Name :: atom(), Dir :: file:filename().

从代码路径中删除目录。

该参数是原子或完整目录名称的列表。 如果 Name 是一个原子,则代码路径中名称为 .../Name[-Vsn][/ebin] 的目录将被删除。

始终返回 ok,无论每个单独的 NamesOrDirs 是否有效。

-spec delete(Module) -> boolean() when Module :: module().

删除 Module 的当前代码,即 Module 的当前代码将变为旧代码。

这意味着进程可以继续执行模块中的代码,但不能对其进行外部函数调用。

如果成功,则返回 true;如果 Module 存在必须首先清除的旧代码,或者如果 Module 不是(已加载的)模块,则返回 false

-spec ensure_loaded(Module) -> {module, Module} | {error, What}
                       when Module :: module(), What :: embedded | badfile | nofile | on_load_failure.

尝试以与 load_file/1 相同的方式加载模块,除非该模块已经加载。

如果并发调用,此函数确保在给定时间只有一个进程尝试加载所述模块。

在嵌入模式下,它不会加载尚未加载的模块,而是返回 {error, embedded}。 有关其他可能错误原因的说明,请参阅 代码加载函数的错误原因

此函数的链接

ensure_modules_loaded(Modules)

查看源代码 (自 OTP 19.0 起)
-spec ensure_modules_loaded([Module]) -> ok | {error, [{Module, What}]}
                               when Module :: module(), What :: badfile | nofile | on_load_failure.

尝试以与 load_file/1 相同的方式加载列表 Modules 中尚未加载的任何模块。

ensure_loaded/1 不同,即使在 embedded 模式下也会加载模块。

如果成功,则返回 ok;如果某些模块加载失败,则返回 {error,[{Module,Reason}]}。 有关其他可能错误原因的说明,请参阅 代码加载函数的错误原因

此函数的链接

finish_loading(Prepared)

查看源代码 (自 OTP 19.0 起)
-spec finish_loading(Prepared) -> ok | {error, [{Module, What}]}
                        when
                            Prepared :: prepared_code(),
                            Module :: module(),
                            What :: not_purged | sticky_directory | pending_on_load.

尝试加载先前由 prepare_loading/1 准备的所有模块的代码。

加载是原子发生的,这意味着要么所有模块同时加载,要么不加载任何模块。

此函数可能因以下错误原因之一而失败:

  • not_purged - 无法加载对象代码,因为该代码的旧版本已经存在。

  • sticky_directory - 对象代码驻留在粘性目录中。

  • pending_on_load - 先前加载的模块包含一个从未完成的 -on_load 函数。

此函数的链接

get_coverage(Level, Module)

查看源代码 (自 OTP 27.0 起)
-spec get_coverage(Level, module()) -> Result
                      when
                          Level :: function | line | cover_id_line,
                          Result :: [{Entity, CoverageInfo}],
                          Entity :: {Function, Arity} | Line | CoverId,
                          CoverageInfo :: Covered | Counter,
                          Function :: atom(),
                          Arity :: arity(),
                          Line :: non_neg_integer(),
                          CoverId :: pos_integer(),
                          Covered :: boolean(),
                          Counter :: non_neg_integer().

返回模块 Modulefunctionline 覆盖率数据。

如果 Level 为 function,则根据给定模块的 覆盖率模式 返回该模块的函数覆盖率

  • function - 对于模块 Module 中的每个函数,返回一个布尔值,指示该函数是否已至少执行一次。

  • function_counters - 对于模块 Module 中的每个函数,返回一个整数,表示该行已执行的次数。

  • line - 对于模块 Module 中的每个函数,返回一个布尔值,指示该函数是否已至少执行一次。

  • line_counters - 对于模块 Module 中的每个函数,返回一个布尔值,指示该函数是否至少执行过一次(请注意,在此模式下,无法检索每个函数执行的次数计数器)。

如果 Level 是 line,则根据其覆盖模式返回给定模块的行覆盖率。

  • line - 对于模块中的每个可执行行,返回一个布尔值,指示该行是否至少执行过一次。

  • line_counters - 对于模块中的每个可执行行,返回一个整数,表示该行被执行的次数。

cover_id_line 级别由 cover 工具使用。

失败情况

  • badarg - 如果 Level 不是 functionline

  • badarg - 如果 Module 不是一个原子。

  • badarg - 如果 Module 没有引用已加载的模块。

  • badarg - 如果 Module 的加载覆盖模式不是 none

  • badarg - 如果 Level 是 line 并且 Module 的加载未启用 lineline_counters

  • badarg - 如果运行时系统不支持覆盖率。

另请参阅: 原生覆盖率支持

此函数的链接

get_coverage_mode()

查看源代码 (自 OTP 27.0 起)
-spec get_coverage_mode() -> Mode when Mode :: coverage_mode().

返回由 erl 的选项 +JPcoverset_coverage_mode/1 设置的覆盖率模式。

失败

  • badarg - 如果运行时系统不支持覆盖率。

另请参阅: 原生覆盖率支持

此函数的链接

get_coverage_mode(Module)

查看源代码 (自 OTP 27.0 起)
-spec get_coverage_mode(Module) -> Mode when Module :: module(), Mode :: coverage_mode().

获取给定模块的覆盖率模式。

失败情况

  • badarg - 如果 Module 不是一个原子。

  • badarg - 如果 Module 没有引用已加载的模块。

  • badarg - 如果运行时系统不支持覆盖率。

另请参阅: 原生覆盖率支持

此函数的链接

get_doc(Module)

查看源代码 (自 OTP 23.0 起)
-spec get_doc(Mod) -> {ok, Res} | {error, Reason}
                 when
                     Mod :: module(),
                     Res ::
                         #docs_v1{anno :: term(),
                                  beam_language :: term(),
                                  format :: term(),
                                  module_doc :: term(),
                                  metadata :: term(),
                                  docs :: term()},
                     Reason :: non_existing | missing | file:posix().

如果可用,则返回 ModuleEEP 48 样式文档。

如果在代码路径中找不到 Module,此函数返回 {error,non_existing}

如果找不到文档,此函数会尝试从模块中的调试信息生成文档。 如果没有可用的调试信息,此函数返回 {error,missing}

有关文档块的更多信息,请参阅 Kernel 用户指南中的 文档存储和格式

此函数的链接

get_mode()

查看源代码 (自 OTP R16B 起)
-spec get_mode() -> embedded | interactive.

返回一个原子,描述代码服务器的模式:interactiveembedded

当外部实体(例如,IDE)为正在运行的节点提供额外的代码时,此信息非常有用。如果代码服务器处于交互模式,则只需将路径添加到代码中。如果代码服务器处于嵌入模式,则必须使用 load_binary/3 加载代码。

此函数的链接

get_object_code(Module)

查看源代码
-spec get_object_code(Module) -> {Module, Binary, Filename} | error
                         when Module :: module(), Binary :: binary(), Filename :: file:filename().

如果代码路径中找到,则返回模块 Module 的对象代码。

如果成功,则返回 {Module, Binary, Filename},否则返回 errorBinary 是一个二进制数据对象,其中包含模块的目标代码。如果要在分布式系统中的远程节点上加载代码,这将非常有用。例如,在节点 Node 上加载模块 Module 的操作如下:

...
{_Module, Binary, Filename} = code:get_object_code(Module),
erpc:call(Node, code, load_binary, [Module, Filename, Binary]),
...
-spec get_path() -> Path when Path :: [Dir :: file:filename()].

返回代码路径。

-spec is_loaded(Module) -> {file, Loaded} | false when Module :: module(), Loaded :: loaded_filename().

检查是否已加载 Module

如果是,则返回 {file, Loaded},否则返回 false

通常,Loaded 是从中获取代码的绝对文件名 Filename。如果模块是预加载的(请参阅 script(4)),则 Loaded =:= preloaded。如果模块是 Cover 编译的(请参阅 cover),则 Loaded =:= cover_compiled

-spec is_sticky(Module) -> boolean() when Module :: module().

如果 Module 是从粘性目录加载的模块的名称(换句话说:尝试重新加载模块将失败),则返回 true;如果 Module 不是已加载的模块或不是粘性的,则返回 false

-spec lib_dir() -> file:filename().

返回库目录,$OTPROOT/lib,其中 $OTPROOT 是 Erlang/OTP 的根目录。

示例

1> code:lib_dir().
"/usr/local/otp/lib"
-spec lib_dir(Name) -> file:filename() | {error, bad_name} when Name :: atom().

返回应用程序 Name库目录(顶层目录)的路径,该应用程序位于 $OTPROOT/lib 下或环境变量 ERL_LIBS 引用的目录中。

如果代码路径中存在名为 NameName-Vsn 的常规目录,并且该目录具有 ebin 子目录,则返回此目录的路径(而不是 ebin 目录)。

如果该目录指向存档中的目录,则在返回路径之前将删除存档名称。例如,如果路径中存在目录 /usr/local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin,则返回 /usr/local/otp/lib/mnesia-4.2.2/ebin。这意味着,无论应用程序是否位于存档中,应用程序的库目录都是相同的。

警告

存档是实验性的。在未来的版本中,它们可能会被删除或其行为可能会发生变化。

示例

> code:lib_dir(mnesia).
"/usr/local/otp/lib/mnesia-4.23"

如果 Name 不是 $OTPROOT/lib 下的应用程序的名称或通过环境变量 ERL_LIBS 引用的目录的名称,则返回 {error, bad_name}。 如果 Name 类型错误,则会引发异常。

警告

为了向后兼容,也允许 Name 是一个字符串。 这可能会在未来的版本中发生更改。

此函数已弃用。 code:lib_dir/2 已弃用;此功能将在未来的版本中删除。
-spec lib_dir(Name, SubDir) -> file:filename() | {error, bad_name} when Name :: atom(), SubDir :: atom().

返回应用程序顶层目录下的子目录的路径。

更改

此函数是存档支持的一部分,这是一项实验性功能,将在未来的版本中更改或删除。

通常,子目录位于应用程序的顶层目录下,但是当应用程序至少部分位于存档中时,情况会有所不同。 一些子目录可以作为常规目录存在,而另一些子目录可以位于存档文件中。 不会检查此目录是否存在。

请使用 code:lib_dir/1filename:join/2 来代替使用此函数。

示例

1> filename:join(code:lib_dir(megaco), "priv").
"/usr/local/otp/lib/megaco-3.9.1.1/priv"

如果 NameSubDir 类型错误,则会引发异常。

-spec load_abs(Filename) -> load_ret() when Filename :: file:filename().

等效于 load_file(Module),不同之处在于 Filename 是绝对或相对文件名。

不会搜索代码路径。它以与 load_file/1 相同的方式返回值。 请注意,Filename 不能包含扩展名(例如,.beam),因为 load_abs/1 会添加正确的扩展名。

此函数的链接

load_binary(Module, Filename, Binary)

查看源代码
-spec load_binary(Module, Filename, Binary) -> {module, Module} | {error, What}
                     when
                         Module :: module(),
                         Filename :: loaded_filename(),
                         Binary :: binary(),
                         What :: badarg | load_error_rsn().

从二进制文件加载对象代码。

此函数可用于在远程 Erlang 节点上加载目标代码。 参数 Binary 必须包含 Module 的目标代码。Filename 仅由代码服务器使用,以记录 Module 的目标代码来自哪个文件。 因此,代码服务器不会打开并读取 Filename

如果成功,则返回 {module, Module},如果加载失败,则返回 {error, Reason}。 有关可能的错误原因的说明,请参阅 代码加载函数的错误原因

-spec load_file(Module) -> load_ret() when Module :: module().

尝试使用代码路径加载 Erlang 模块 Module

它会查找扩展名与所使用的 Erlang 机器对应的目标代码文件,例如 Module.beam。 如果目标代码中找到的模块名称与名称 Module 不同,则加载失败。 使用 load_binary/3 加载模块名称与文件名不同的目标代码。

如果成功,则返回 {module, Module},如果加载失败,则返回 {error, Reason}。 有关可能的错误原因的说明,请参阅 代码加载函数的错误原因

此函数的链接

modified_modules()

查看源代码 (自 OTP 20.0 起)
-spec modified_modules() -> [module()].

返回 module_status/1 返回 modified 的所有当前已加载模块的列表。

另请参阅 all_loaded/0

此函数的链接

module_status()

查看源代码 (自 OTP 23.0 起)
-spec module_status() -> [{module(), module_status()}].

有关详细信息,请参阅 module_status/1all_loaded/0

此函数的链接

module_status(Module)

查看源代码 (自 OTP 20.0 起)
-spec module_status(Module :: module() | [module()]) -> module_status() | [{module(), module_status()}].

返回 Module 相对于磁盘上对象文件的状态。

模块的状态可以是以下之一:

  • not_loaded - 如果当前未加载 Module

  • loaded - 如果已加载 Module,并且目标文件存在并包含相同的代码。

  • removed - 如果已加载 Module,但在代码路径中找不到相应的目标文件。

  • modified - 如果已加载 Module,但目标文件包含具有不同 MD5 校验和的代码。

预加载的模块始终报告为 loaded,而不检查磁盘上的内容。如果存在目标文件,则 Cover 编译的模块始终报告为 modified,否则报告为 removed。加载路径为空字符串(这是自动生成代码的约定)的模块只会报告为 loadednot_loaded

另请参阅 modified_modules/0

-spec objfile_extension() -> nonempty_string().

返回与所使用的 Erlang 机器相对应的对象代码文件扩展名。

对于官方 Erlang/OTP 版本,返回值始终为 .beam

此函数的链接

prepare_loading(Modules)

查看源代码 (自 OTP 19.0 起)
-spec prepare_loading(Modules) -> {ok, Prepared} | {error, [{Module, What}]}
                         when
                             Modules :: [Module | {Module, Filename, Binary}],
                             Module :: module(),
                             Filename :: file:filename(),
                             Binary :: binary(),
                             Prepared :: prepared_code(),
                             What :: badfile | nofile | on_load_not_allowed | duplicated.

准备加载列表 Modules 中的模块。

通过调用 finish_loading(Prepared) 完成加载。

此函数可能因以下错误原因之一而失败:

  • badfile - 对象代码格式不正确,或者对象代码中的模块名称不是预期的模块名称。

  • nofile - 不存在包含对象代码的文件。

  • on_load_not_allowed - 模块包含一个 -on_load 函数

  • duplicated - 模块在 Modules 中被多次包含。

-spec priv_dir(Name) -> file:filename() | {error, bad_name} when Name :: atom().

返回应用程序中 priv 目录的路径。

警告

为了向后兼容,也允许 Name 是一个字符串。 这可能会在未来的版本中发生更改。

-spec purge(Module) -> boolean() when Module :: module().

清除 Module 的代码,即删除标记为旧的代码。

如果一些进程仍然停留在旧代码中,这些进程将在删除代码之前被终止。

更改

从 Erlang/OTP 20.0 开始,只有当进程直接引用代码时,才认为进程停留在代码中。有关更多信息,请参阅 erlang:check_process_code/3 的文档,该文档用于确定进程是否停留。

如果成功并且需要终止任何进程,则返回 true,否则返回 false

此函数的链接

replace_path(Name, Dir)

查看源代码
-spec replace_path(Name, Dir) -> replace_path_ret() when Name :: atom(), Dir :: file:filename().

等同于 replace_path(Name, Dir, nocache)

此函数的链接

replace_path(Name, Dir, Cache)

查看源代码 (自 OTP 26.0 起)
-spec replace_path(Name, Dir, cache()) -> replace_path_ret() when Name :: atom(), Dir :: file:filename().

将代码路径中旧的目录 .../Name[-Vsn][/ebin] 替换为 Dir

如果 Name 不存在,它会将新目录 Dir 添加到代码路径的末尾。新目录的名称也必须是 .../Name[-Vsn][/ebin]。如果要向正在运行的系统添加目录(库)的新版本,则应使用此函数。

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

返回:

  • true - 如果成功

  • {error, bad_name} - 如果找不到 Name

  • {error, bad_directory} - 如果 Dir 不存在

  • {error, {badarg, [Name, Dir]}} - 如果 NameDir 无效

此函数的链接

reset_coverage(Module)

查看源代码 (自 OTP 27.0 起)
-spec reset_coverage(Module) -> ok when Module :: module().

重置模块 Module 的覆盖率信息。

如果 覆盖率模式functionline,则用于跟踪 Module 中已执行函数或行的所有布尔值都设置为 false

如果覆盖率模式为 function_countersline_counters,则 Module 的所有计数器都将重置为零。

失败情况

  • badarg - 如果 Module 不是一个原子。

  • badarg - 如果 Module 没有引用已加载的模块。

  • badarg - 如果加载 Module 时未启用覆盖率。

  • badarg - 如果运行时系统不支持覆盖率。

另请参阅: 原生覆盖率支持

-spec root_dir() -> file:filename().

返回 Erlang/OTP 的根目录,即安装目录。

示例

1> code:root_dir().
"/usr/local/otp"
此函数的链接

set_coverage_mode(Mode)

查看源代码 (自 OTP 27.0 起)
-spec set_coverage_mode(Mode) -> OldMode when Mode :: coverage_mode(), OldMode :: coverage_mode().

为后续加载的模块设置覆盖率模式,类似于 erl 的选项 +JPcover

覆盖率模式会对在此调用之后加载的代码产生以下影响

  • function - 所有加载的模块都将被检测,以跟踪哪些函数被执行。可以通过调用 get_coverage(function, Module) 来检索有关已执行函数的信息。

  • function_counters - 所有加载的模块都将被检测,以计算每个函数被执行的次数。可以通过调用 get_coverage(function, Module) 来检索每个函数被执行次数的信息。

  • line - 当加载使用 line_coverage 选项编译的模块时,它们将被检测以跟踪哪些行已被执行。可以通过调用 get_coverage(line, Module) 来检索有关已执行行的信息,并且可以通过调用 get_coverage(function, Module) 来检索有关已执行函数的信息。

  • line_counters - 当加载使用 line_coverage 选项编译的模块时,它们将被检测以计算每行被执行的次数。可以通过调用 get_coverage(line, Module) 来检索每行被执行次数的信息,并且可以通过调用 get_coverage(function, Module) 来检索有关已执行函数的信息(请注意,在此模式下,无法检索每个函数被执行次数的计数器)。

  • none - 将加载模块,而不进行覆盖率检测。

返回先前的覆盖率模式。

失败情况

  • badarg - 如果 Mode 不是有效的覆盖率模式。

  • badarg - 如果运行时系统不支持覆盖率。

另请参阅: 原生覆盖率支持

-spec set_path(Path) -> set_path_ret() when Path :: [Dir :: file:filename()].

等同于 set_path(PathList, nocache)

此函数的链接

set_path(PathList, Cache)

查看源代码 (自 OTP 26.0 起)
-spec set_path(Path, cache()) -> set_path_ret() when Path :: [Dir :: file:filename()].

将代码路径设置为目录列表 Path

参数 Cache 控制是否在首次遍历时缓存目录内容。如果 Cachecache,则会缓存目录内容;如果 Cachenocache,则不会缓存。

返回:

  • true - 如果成功

  • {error, bad_directory} - 如果任何 Dir 不是目录名

-spec soft_purge(Module) -> boolean() when Module :: module().

清除 Module 的代码,即删除标记为旧的代码,但前提是没有进程仍在其中运行。

更改

从 Erlang/OTP 20.0 开始,只有当进程直接引用代码时,才认为进程停留在代码中。有关更多信息,请参阅 erlang:check_process_code/3 的文档,该文档用于确定进程是否停留。

如果由于旧代码中残留的进程而无法清除模块,则返回 false,否则返回 true

-spec stick_dir(Dir) -> ok | error when Dir :: file:filename().

Dir 标记为粘性目录。

如果成功,则返回 ok,否则返回 error

-spec unstick_dir(Dir) -> ok | error when Dir :: file:filename().

取消标记为粘性目录的目录。

如果成功,则返回 ok,否则返回 error

此函数的链接

where_is_file(Filename)

查看源代码
-spec where_is_file(Filename) -> non_existing | Absname
                       when Filename :: file:filename(), Absname :: file:filename().

在代码路径中搜索 Filename,这是一个任意类型的文件。

如果找到,则返回完整名称。如果找不到该文件,则返回 non_existing。例如,该函数可用于定位应用程序资源文件。

-spec which(Module) -> Which when Module :: module(), Which :: loaded_filename() | non_existing.

如果模块未加载,此函数将在代码路径中搜索包含 Module 对象代码的第一个文件,并返回绝对文件名。

  • 如果模块已加载,则返回包含已加载目标代码的文件的名称。

  • 如果模块是预加载的,则返回 preloaded

  • 如果模块是 Cover 编译的,则返回 cover_compiled

  • 如果找不到该模块,则返回 non_existing