26using IKVM.ByteCode.Decoding;
36 sealed partial class ClassFile
39 internal sealed partial class Method : FieldOrMethod
45 MethodParametersEntry[] parameters;
55 internal Method(ClassFile classFile,
string[] utf8_cp,
ClassFileParseOptions options,
IKVM.ByteCode.Decoding.Method reader) :
56 base(classFile, utf8_cp, reader.AccessFlags, reader.
Name, reader.Descriptor)
60 if (ReferenceEquals(
Name, StringConstants.CLINIT) && ReferenceEquals(Signature, StringConstants.SIG_VOID) && (classFile.MajorVersion < 51 || IsStatic))
62 accessFlags &= Modifiers.Strictfp;
63 accessFlags |= (Modifiers.Static | Modifiers.Private);
69 if ((ReferenceEquals(Name, StringConstants.INIT) && (IsStatic || IsSynchronized || IsFinal || IsAbstract || IsNative))
70 || (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
71 || (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized))
72 || (classFile.IsInterface && classFile.MajorVersion <= 51 && (!IsPublic || IsFinal || IsNative || IsSynchronized || !IsAbstract))
73 || (classFile.IsInterface && classFile.MajorVersion >= 52 && (!(IsPublic || IsPrivate) || IsFinal || IsNative || IsSynchronized)))
75 throw new ClassFormatError(
"Method {0} in class {1} has illegal modifiers: 0x{2:X}", Name, classFile.Name, (int)accessFlags);
79 for (
int i = 0; i < reader.Attributes.Count; i++)
81 var attribute = reader.Attributes[i];
83 switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Name))
85 case AttributeName.Deprecated:
86 var deprecatedAttribute = (DeprecatedAttribute)attribute;
87 flags |= FLAG_MASK_DEPRECATED;
89 case AttributeName.Code:
91 var codeAttribute = (CodeAttribute)attribute;
92 if (code.IsEmpty ==
false)
93 throw new ClassFormatError(
"{0} (Duplicate Code attribute)", classFile.Name);
95 code.Read(classFile, utf8_cp,
this, codeAttribute, options);
98 case AttributeName.Exceptions:
100 if (exceptions !=
null)
101 throw new ClassFormatError(
"{0} (Duplicate Exceptions attribute)", classFile.Name);
103 var exceptionsAttribute = (ExceptionsAttribute)attribute;
104 exceptions =
new string[exceptionsAttribute.Exceptions.Count];
105 for (
int j = 0; j < exceptionsAttribute.Exceptions.Count; j++)
106 exceptions[j] = classFile.GetConstantPoolClass(exceptionsAttribute.Exceptions[j]);
110 case AttributeName.Signature:
111 if (classFile.MajorVersion < 49)
114 var signatureAttribute = (
IKVM.ByteCode.Decoding.SignatureAttribute)attribute;
115 signature = classFile.GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Signature);
117 case AttributeName.RuntimeVisibleAnnotations:
118 if (classFile.MajorVersion < 49)
121 var runtimeVisibleAnnotationsAttribute = (RuntimeVisibleAnnotationsAttribute)attribute;
122 annotations = ReadAnnotations(runtimeVisibleAnnotationsAttribute.Annotations, classFile, utf8_cp);
125 foreach (
object[] annot
in annotations)
127 switch ((
string)annot[1])
130 case "Lsun/reflect/CallerSensitive;":
131 flags |= FLAG_CALLERSENSITIVE;
134 case "Ljava/lang/invoke/LambdaForm$Compiled;":
135 flags |= FLAG_LAMBDAFORM_COMPILED;
137 case "Ljava/lang/invoke/LambdaForm$Hidden;":
138 flags |= FLAG_LAMBDAFORM_HIDDEN;
140 case "Ljava/lang/invoke/ForceInline;":
141 flags |= FLAG_FORCEINLINE;
147 case AttributeName.RuntimeVisibleParameterAnnotations:
148 if (classFile.MajorVersion < 49)
151 var runtimeVisibleParameterAnnotationsAttribute = (RuntimeVisibleParameterAnnotationsAttribute)attribute;
152 low ??=
new LowFreqData();
153 low.parameterAnnotations =
new object[runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations.Count][];
154 for (
int j = 0; j < runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations.Count; j++)
156 var parameter = runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations[j];
157 low.parameterAnnotations[j] =
new object[parameter.Annotations.Count];
158 for (
int k = 0; k < parameter.Annotations.Count; k++)
159 low.parameterAnnotations[j][k] = ReadAnnotation(parameter.Annotations[k], classFile, utf8_cp);
163 case AttributeName.AnnotationDefault:
164 if (classFile.MajorVersion < 49)
167 var annotationDefaultAttribute = (
IKVM.ByteCode.Decoding.AnnotationDefaultAttribute)attribute;
168 low ??=
new LowFreqData();
169 low.annotationDefault = ReadAnnotationElementValue(annotationDefaultAttribute.DefaultValue, classFile, utf8_cp);
173 case AttributeName.RuntimeInvisibleAnnotations:
174 if (classFile.MajorVersion < 49)
177 var runtimeInvisibleAnnotationsAttribute = (RuntimeInvisibleAnnotationsAttribute)attribute;
179 foreach (
object[] annot
in ReadAnnotations(runtimeInvisibleAnnotationsAttribute.Annotations, classFile, utf8_cp))
181 if (annot[1].Equals(
"Likvm/lang/Internal;"))
183 if (classFile.IsInterface)
185 classFile.diagnostics.InterfaceMethodCantBeInternal(classFile.Name,
Name, Signature);
190 flags |= FLAG_MASK_INTERNAL;
193 else if (annot[1].Equals(
"Likvm/internal/InterlockedCompareAndSet;"))
196 for (
int j = 2; j < annot.Length; j += 2)
197 if (annot[j].Equals(
"value") && annot[j + 1] is
string)
198 field = (string)annot[j + 1];
202 low ??=
new LowFreqData();
203 low.InterlockedCompareAndSetField = field;
206 else if (annot[1].Equals(
"Likvm/lang/ModuleInitializer;"))
208 if (classFile.IsInterface || IsConstructor || IsClassInitializer || IsPrivate || IsStatic ==
false)
210 classFile.diagnostics.ModuleInitializerMethodRequirements(classFile.Name,
Name, Signature);
214 flags |= FLAG_MODULE_INITIALIZER;
221 case AttributeName.MethodParameters:
222 if (classFile.MajorVersion < 52)
225 if (parameters !=
null)
226 throw new ClassFormatError(
"{0} (Duplicate MethodParameters attribute)", classFile.Name);
228 var methodParametersAttribute = (
IKVM.ByteCode.Decoding.MethodParametersAttribute)attribute;
229 parameters = ReadMethodParameters(methodParametersAttribute.Parameters, utf8_cp);
232 case AttributeName.RuntimeVisibleTypeAnnotations:
233 if (classFile.MajorVersion < 52)
236 var runtimeVisibleTypeAnnotationsAttribute = (
IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute;
237 classFile.CreateUtf8ConstantPoolItems(utf8_cp);
238 runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotationsAttribute.TypeAnnotations;
244 if (IsAbstract || IsNative)
248 throw new ClassFormatError(
"Code attribute in native or abstract methods in class file " + classFile.Name);
255 if (ReferenceEquals(this.
Name, StringConstants.CLINIT))
257 code.verifyError =
string.Format(
"Class {0}, method {1} signature {2}: No Code attribute", classFile.Name,
this.Name,
this.Signature);
260 throw new ClassFormatError(
"Absent Code attribute in method that is not native or abstract in class file " + classFile.Name);
265 private static MethodParametersEntry[] ReadMethodParameters(MethodParameterTable parameters,
string[] utf8_cp)
267 var l =
new MethodParametersEntry[parameters.Count];
269 for (
int i = 0; i < parameters.Count; i++)
271 var name = parameters[i].Name;
272 if (name.Slot >= utf8_cp.Length || (name.IsNotNil && utf8_cp[name.Slot] ==
null))
273 return MethodParametersEntry.Malformed;
275 l[i].name = utf8_cp[name.Slot];
276 l[i].accessFlags = parameters[i].AccessFlags;
282 protected override void ValidateSig(ClassFile classFile,
string descriptor)
286 throw new ClassFormatError(
"{0} (Method \"{1}\" has invalid signature \"{2}\")", classFile.Name,
this.Name, descriptor);
290 internal bool IsStrictfp => (accessFlags &
Modifiers.Strictfp) != 0;
292 internal bool IsVirtual => (accessFlags & (Modifiers.Static |
Modifiers.Private)) == 0 && !IsConstructor;
295 internal bool IsClassInitializer => ReferenceEquals(
Name, StringConstants.CLINIT) && ReferenceEquals(Signature, StringConstants.SIG_VOID) && IsStatic;
297 internal bool IsConstructor => ReferenceEquals(
Name, StringConstants.INIT);
299 internal bool IsCallerSensitive => (flags & FLAG_CALLERSENSITIVE) != 0;
301 internal bool IsLambdaFormCompiled => (flags & FLAG_LAMBDAFORM_COMPILED) != 0;
303 internal bool IsLambdaFormHidden => (flags & FLAG_LAMBDAFORM_HIDDEN) != 0;
305 internal bool IsForceInline => (flags & FLAG_FORCEINLINE) != 0;
307 internal string[] ExceptionsAttribute => exceptions;
309 internal object[][] ParameterAnnotations => low ==
null ? null : low.parameterAnnotations;
311 internal object AnnotationDefault => low ==
null ? null : low.annotationDefault;
315 internal string InterlockedCompareAndSetField => low ==
null ? null : low.InterlockedCompareAndSetField;
322 internal int[] ArgMap => code.argmap;
324 internal int MaxStack => code.max_stack;
326 internal int MaxLocals => code.max_locals;
330 get => code.instructions;
331 set => code.instructions = value;
336 get => code.exception_table;
337 set => code.exception_table = value;
344 internal MethodParametersEntry[] MethodParameters => parameters;
346 internal bool MalformedMethodParameters => parameters == MethodParametersEntry.Malformed;
348 internal bool HasJsr => code.hasJsr;
global::java.lang.invoke.LambdaForm.Name Name
static bool IsValidMethodDescriptor(string descriptor)
Returns true if the specified descriptor is a valid method descriptor.
IKVM.Runtime.ClassFile.Method.Instruction Instruction
IKVM.Runtime.ClassFile.Method.LocalVariableTableEntry LocalVariableTableEntry
IKVM.Runtime.ClassFile.Method.ExceptionTableEntry ExceptionTableEntry