定义
Synchronization
Synchronization in the Java Virtual Machine is implemented by monitor entry and exit, either explicitly (by use of the monitorenter and monitorexit instructions) or implicitly (by the method invocation and return instructions).
Java虚拟机中的同步是通过监视入口和出口实现的,可以是显式的(通过使用monitorenter和monitorexit指令),也可以是隐式的(通过方法调用和返回指令)。
For code written in the Java programming language, perhaps the most common form of synchronization is the synchronized
method. A synchronized
method is not normally implemented using monitorenter and monitorexit. Rather, it is simply distinguished in the run-time constant pool by the ACC_SYNCHRONIZED
flag, which is checked by the method invocation instructions (§2.11.10).
对于用Java编程语言编写的代码,最常见的同步形式可能是synchronized方法。同步方法通常不使用monitorenter和monitorexit实现。相反,它只是通过ACC_SYNCHRONIZED标志在运行时常量池中进行区分,该标志由方法调用指令(2.11.10)检查。
The monitorenter and monitorexit instructions enable the compilation of synchronized
statements.
monitorenter 和monitorexit 指令可以由synchronized 语句编译生成。
The compiler ensures that at any method invocation completion, a monitorexit instruction will have been executed for each monitorenter instruction executed since the method invocation. This is the case whether the method invocation completes normally (§2.6.4) or abruptly (§2.6.5). To enforce proper pairing of monitorenter and monitorexit instructions on abrupt method invocation completion, the compiler generates exception handlers (§2.10) that will match any exception and whose associated code executes the necessary monitorexit instructions.
编译器确保在任何方法调用完成时,对于自方法调用以来执行的每个monitorenter指令,都会执行monitorexit指令。方法调用是正常完成(2.6.4)还是突然完成(2.6.5)。为了在突然的方法调用完成时强制执行monitorenter和monitorexit指令的正确配对,编译器生成异常处理程序(2.10),它将匹配任何异常,其相关代码将执行必要的monitorexit指令。
The Java Virtual Machine supports synchronization of both methods and sequences of instructions within a method by a single synchronization construct: the monitor.
Java虚拟机通过一个同步结构(监视器)支持方法中的方法和指令序列的同步。
Method-level synchronization is performed implicitly, as part of method invocation and return (§2.11.8). A synchronized
method is distinguished in the run-time constant pool's method_info
structure (§4.6) by the ACC_SYNCHRONIZED
flag, which is checked by the method invocation instructions. When invoking a method for which ACC_SYNCHRONIZED
is set, the executing thread enters a monitor, invokes the method itself, and exits the monitor whether the method invocation completes normally or abruptly. During the time the executing thread owns the monitor, no other thread may enter it. If an exception is thrown during invocation of the synchronized
method and the synchronized
method does not handle the exception, the monitor for the method is automatically exited before the exception is rethrown out of the synchronized
method.
方法级同步是隐式执行的,作为方法调用和返回的一部分(第2.18.8节)。 同步方法在运行时常量池的method_info结构(第4.6节)中由ACC_SYNCHRONIZED标志区分,该标志由方法调用指令检查。 当调用设置了ACC_SYNCHRONIZED的方法时,执行线程进入监视器,调用方法本身,并退出监视器,方法调用是正常还是突然完成。 在执行线程拥有监视器期间,没有其他线程可以输入它。 如果在调用synchronized方法期间抛出异常并且synchronized方法不处理异常,则在异步从同步方法中重新抛出之前,将自动退出该方法的监视器。
Synchronization of sequences of instructions is typically used to encode the synchronized
block of the Java programming language. The Java Virtual Machine supplies the monitorenter and monitorexit instructions to support such language constructs. Proper implementation of synchronized
blocks requires cooperation from a compiler targeting the Java Virtual Machine (§3.14).
指令序列的同步通常用于编码Java编程语言的同步块。 Java虚拟机提供monitorenter和monitorexit指令以支持此类语言结构。 正确实现同步块需要来自针对Java虚拟机(第3.14节)的编译器的合作。
Structured locking is the situation when, during a method invocation, every exit on a given monitor matches a preceding entry on that monitor. Since there is no assurance that all code submitted to the Java Virtual Machine will perform structured locking, implementations of the Java Virtual Machine are permitted but not required to enforce both of the following two rules guaranteeing structured locking. Let T be a thread and M be a monitor. Then:
-
The number of monitor entries performed by T on M during a method invocation must equal the number of monitor exits performed by T on M during the method invocation whether the method invocation completes normally or abruptly.
-
At no point during a method invocation may the number of monitor exits performed by T on M since the method invocation exceed the number of monitor entries performed by T on M since the method invocation.
结构化锁定是指在方法调用期间,给定监视器上的每个出口与该监视器上的前一个条目匹配时的情况。由于无法保证提交给Java虚拟机的所有代码都将执行结构化锁定,因此允许Java虚拟机实现,但不需要强制执行以下两个保证结构化锁定的规则。设T为线程,M为监视器。然后:
- 在方法调用期间由T在M上执行的监视器条目的数量必须等于方法调用期间由T在M上执行的监视器退出的数量,无论方法调用是正常还是突然完成。
- 在方法调用期间,在方法调用期间,由于方法调用,由T在M上执行的监视器退出的数量可能超过自从方法调用以来由T在M上执行的监视器条目的数量。
Note that the monitor entry and exit automatically performed by the Java Virtual Machine when invoking synchronized
method are considered to occur during the calling method's invocation.
请注意,在调用方法的调用期间,会考虑在调用synchronized方法时由Java虚拟机自动执行的监视器进入和退出。
Methods
Each method, including each instance initialization method (§2.9) and the class or interface initialization method (§2.9), is described by a method_info
structure. No two methods in one class
file may have the same name and descriptor (§4.3.3).
每个方法(包括每个实例初始化方法(第2.9节)和类或接口初始化方法(第2.9节))都由method_info结构描述。一个类文件中没有两个方法可能具有相同的名称和描述符(第4.3.3节)。
The structure has the following format:
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The items of the method_info
structure are as follows:
access_flags
The value of the access_flags
item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is as shown in Table 4.5.
Table 4.5. Method access and property flags
Flag Name Value Interpretation
ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
ACC_PRIVATE 0x0002 Declared private; accessible only within the defining class.
ACC_PROTECTED 0x0004 Declared protected; may be accessed within subclasses.
ACC_STATIC 0x0008 Declared static.
ACC_FINAL 0x0010 Declared final; must not be overridden (§5.4.5).
ACC_SYNCHRONIZED 0x0020 Declared synchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE 0x0040 A bridge method, generated by the compiler.
ACC_VARARGS 0x0080 Declared with variable number of arguments.
ACC_NATIVE 0x0100 Declared native; implemented in a language other than Java.
ACC_ABSTRACT 0x0400 Declared abstract; no implementation is provided.
ACC_STRICT 0x0800 Declared strictfp; floating-point mode is FP-strict.
ACC_SYNTHETIC 0x1000 Declared synthetic; not present in the source code.
The ACC_VARARGS
flag indicates that this method takes a variable number of arguments at the source code level. A method declared to take a variable number of arguments must be compiled with the ACC_VARARGS
flag set to 1. All other methods must be compiled with the ACC_VARARGS
flag set to 0.
ACC_VARARGS标志指示此方法在源代码级别采用可变数量的参数。声明采用可变数量参数的方法必须ACC_VARARGS标志设置为1的情况下进行编译。所有其他方法必须在ACC_VARARGS标志设置为0的情况下编译。
The ACC_BRIDGE
flag is used to indicate a bridge method generated by a Java compiler.
ACC_BRIDGE标志用于指示Java编译器生成的桥接方法。
A method may be marked with the ACC_SYNTHETIC
flag to indicate that it was generated by a compiler and does not appear in source code, unless it is one of the methods named in §4.7.8.
可以用ACC_SYNTHETIC标志标记方法,以指示它是由编译器生成的,并且不出现在源代码中,除非它是§4.7.8中命名的方法之一。
Methods of classes may set any of the flags in Table 4.5. However, a specific method of a class may have at most one of its ACC_PRIVATE
, ACC_PROTECTED
and ACC_PUBLIC
flags set (JLS §8.4.3). If a specific method has its ACC_ABSTRACT
flag set, it must not have any of its ACC_FINAL
, ACC_NATIVE
, ACC_PRIVATE
, ACC_STATIC
, ACC_STRICT
or ACC_SYNCHRONIZED
flags set (JLS §8.4.3.1, JLS §8.4.3.3, JLS §8.4.3.4).
类的方法可以设置表4.5中的任何标志。但是,类的特定方法最多可以设置一个ACC_PRIVATE,ACC_PROTECTED和ACC_PUBLIC标志(JLS§8.4.3)。如果特定方法设置了ACC_ABSTRACT标志,则它不能设置任何ACC_FINAL,ACC_NATIVE,ACC_PRIVATE,ACC_STATIC,ACC_STRICT或ACC_SYNCHRONIZED标志(JLS§8.4.3.1,JLS§8.4.3.3,JLS§8.4.3.4)。
All interface methods must have their ACC_ABSTRACT
and ACC_PUBLIC
flags set; they may have their ACC_VARARGS
, ACC_BRIDGE
and ACC_SYNTHETIC
flags set and must not have any of the other flags in Table 4.5 set (JLS §9.4).
所有接口方法必须设置其ACC_ABSTRACT和ACC_PUBLIC标志;它们可能设置了ACC_VARARGS,ACC_BRIDGE和ACC_SYNTHETIC标志,并且必须没有表4.5中的任何其他标志(JLS§9.4)。
A specific instance initialization method (§2.9) may have at most one of its ACC_PRIVATE
, ACC_PROTECTED
, and ACC_PUBLIC
flags set, and may also have its ACC_STRICT
, ACC_VARARGS
and ACC_SYNTHETIC
flags set, but must not have any of the other flags in Table 4.5 set.
特定实例初始化方法(第2.9节)最多可设置一个ACC_PRIVATE,ACC_PROTECTED和ACC_PUBLIC标志,并且还可以设置其ACC_STRICT,ACC_VARARGS和ACC_SYNTHETIC标志,但不得具有表4.5中的任何其他标志。
Class and interface initialization methods (§2.9) are called implicitly by the Java Virtual Machine. The value of their access_flags
item is ignored except for the setting of the ACC_STRICT
flag.
类和接口初始化方法(第2.9节)由Java虚拟机隐式调用。 除了ACC_STRICT标志的设置外,它们的access_flags项的值被忽略。
All bits of the access_flags
item not assigned in Table 4.5 are reserved for future use. They should be set to zero in generated class
files and should be ignored by Java Virtual Machine implementations.
表4.5中未分配的access_flags项的所有位都保留供将来使用。它们应该在生成的类文件中设置为零,并且应该被Java虚拟机实现忽略。
name_index
The value of the name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
(§4.4.7) structure representing either one of the special method names (§2.9) <init>
or <clinit>
, or a valid unqualified name (§4.2.2) denoting a method.
name_index项的值必须是constant_pool表的有效索引。该索引处的constant_pool条目必须是CONSTANT_Utf8_info(§4.4.7)结构,表示特殊方法名称之一(§2.9)<init>或<clinit>,或者表示一个有效非限定名称(§4.2.2)方法。
descriptor_index
The value of the descriptor_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
(§4.4.7) structure representing a valid method descriptor (§4.3.3).
descriptor_index项的值必须是constant_pool表的有效索引。该索引处的constant_pool条目必须是表示有效方法描述符(第4.3.3节)的CONSTANT_Utf8_info(§4.4.7)结构。
A future edition of this specification may require that the last parameter descriptor of the method descriptor is an array type if the ACC_VARARGS
flag is set in the access_flags
item.
如果在access_flags项中设置了ACC_VARARGS标志,则此规范的未来版本可能要求方法描述符的最后一个参数描述符是数组类型。
attributes_count
The value of the attributes_count
item indicates the number of additional attributes (§4.7) of this method.
attributes_count项的值表示此方法的附加属性数(第4.7节)。
attributes[]
Each value of the attributes
table must be an attribute structure (§4.7). A method can have any number of optional attributes associated with it.
属性表的每个值必须是属性结构(第4.7节)。方法可以具有与之关联的任意数量的可选属性。
The attributes defined by this specification as appearing in the attributes
table of a method_info
structure are the Code
(§4.7.3), Exceptions
(§4.7.5), Synthetic
(§4.7.8), Signature
(§4.7.9), Deprecated
(§4.7.15), RuntimeVisibleAnnotations
(§4.7.16), RuntimeInvisibleAnnotations
(§4.7.17), RuntimeVisibleParameterAnnotations
(§4.7.18), RuntimeInvisibleParameterAnnotations
(§4.7.19), and AnnotationDefault
(§4.7.20) attributes.
本规范定义的属性出现在method_info结构的属性表中的是Code(§4.7.3),Exceptions(§4.7.5),Synthetic(§4.7.8),Signature(§4.7.9),不推荐使用(§4.7.15),RuntimeVisibleAnnotations(§4.7.16),RuntimeInvisibleAnnotations(§4.7.17),RuntimeVisibleParameterAnnotations(§4.7.18),RuntimeInvisibleParameterAnnotations(§4.7.19)和AnnotationDefault(§4.7.20)属性。
A Java Virtual Machine implementation must recognize and correctly read Code
(§4.7.3) and Exceptions
(§4.7.5) attributes found in the attributes
table of a method_info
structure. If a Java Virtual Machine implementation recognizes class
files whose version number is 49.0 or above, it must recognize and correctly read Signature
(§4.7.9), RuntimeVisibleAnnotations
(§4.7.16), RuntimeInvisibleAnnotations
(§4.7.17), RuntimeVisibleParameterAnnotations
(§4.7.18), RuntimeInvisibleParameterAnnotations
(§4.7.19) and AnnotationDefault
(§4.7.20) attributes found in the attributes
table of a method_info
structure of a class
file whose version number is 49.0 or above.
Java虚拟机实现必须识别并正确读取method_info结构的attributes表中的Code(§4.7.3)和Exceptions(§4.7.5)属性。如果Java虚拟机实现识别版本号为49.0或更高的类文件,则它必须识别并正确读取Signature
(§4.7.9),RuntimeVisibleAnnotations(§4.7.16),RuntimeInvisibleAnnotations(§4.7.17),RuntimeVisibleParameterAnnotations(§) 4.7.18),RuntimeInvisibleParameterAnnotations(§4.7.19)和AnnotationDefault(§4.7.20)属性,在版本号为49.0或更高的类文件的method_info结构的attributes表中找到。
A Java Virtual Machine implementation is required to silently ignore any or all attributes in the attributes
table of a method_info
structure that it does not recognize. Attributes not defined in this specification are not allowed to affect the semantics of the class
file, but only to provide additional descriptive information (§4.7.1).
一个Java虚拟机实现需要静默忽略它无法识别的method_info结构的属性表中的任何或所有属性。没有在本章定义的属性不允许影响属性在类文件的语义,但仅允许提供其他描述性信息(第4.7.1节)。