IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ClassFile.Field.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2015 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25
26using IKVM.Attributes;
27using IKVM.ByteCode;
28using IKVM.ByteCode.Decoding;
30
31namespace IKVM.Runtime
32{
33
34 sealed partial class ClassFile
35 {
36
37 internal sealed class Field : FieldOrMethod
38 {
39
40 object constantValue;
41 string[] propertyGetterSetter;
42
50 internal Field(ClassFile classFile, string[] utf8_cp, IKVM.ByteCode.Decoding.Field field) :
51 base(classFile, utf8_cp, field.AccessFlags, field.Name, field.Descriptor)
52 {
53 if ((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) || (IsFinal && IsVolatile) || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient)))
54 throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, accessFlags);
55
56 for (int i = 0; i < field.Attributes.Count; i++)
57 {
58 var attribute = field.Attributes[i];
59
60 switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Name))
61 {
62 case AttributeName.Deprecated:
63 attribute.AsDeprecated();
64 flags |= FLAG_MASK_DEPRECATED;
65 break;
66 case AttributeName.ConstantValue:
67 try
68 {
69 var _constantValue = (ConstantValueAttribute)attribute;
70 constantValue = Signature switch
71 {
72 "I" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
73 "S" => (short)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
74 "B" => (byte)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
75 "C" => (char)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value),
76 "Z" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value) != 0,
77 "J" => classFile.GetConstantPoolConstantLong((LongConstantHandle)_constantValue.Value),
78 "F" => classFile.GetConstantPoolConstantFloat((FloatConstantHandle)_constantValue.Value),
79 "D" => classFile.GetConstantPoolConstantDouble((DoubleConstantHandle)_constantValue.Value),
80 "Ljava.lang.String;" => classFile.GetConstantPoolConstantString((StringConstantHandle)_constantValue.Value),
81 _ => throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name),
82 };
83 }
84 catch (InvalidCastException)
85 {
86 throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
87 }
88 catch (IndexOutOfRangeException)
89 {
90 throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
91 }
92 catch (InvalidOperationException)
93 {
94 throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
95 }
96 catch (NullReferenceException)
97 {
98 throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
99 }
100 catch (ByteCodeException)
101 {
102 throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
103 }
104 break;
105 case AttributeName.Signature:
106 if (classFile.MajorVersion < 49)
107 goto default;
108
109 var _signature = (IKVM.ByteCode.Decoding.SignatureAttribute)attribute;
110 signature = classFile.GetConstantPoolUtf8String(utf8_cp, _signature.Signature);
111 break;
112 case AttributeName.RuntimeVisibleAnnotations:
113 if (classFile.MajorVersion < 49)
114 goto default;
115
116 var _runtimeVisibleAnnotation = (RuntimeVisibleAnnotationsAttribute)attribute;
117 annotations = ReadAnnotations(_runtimeVisibleAnnotation.Annotations, classFile, utf8_cp);
118 break;
119 case AttributeName.RuntimeInvisibleAnnotations:
120 if (classFile.MajorVersion < 49)
121 goto default;
122
123 var _runtimeInvisibleAnnotations = (RuntimeInvisibleAnnotationsAttribute)attribute;
124
125 foreach (object[] annot in ReadAnnotations(_runtimeInvisibleAnnotations.Annotations, classFile, utf8_cp))
126 {
127 if (annot[1].Equals("Likvm/lang/Property;"))
128 DecodePropertyAnnotation(classFile, annot);
129#if IMPORTER
130 else if(annot[1].Equals("Likvm/lang/Internal;"))
131 {
132 this.accessFlags &= ~Modifiers.AccessMask;
133 flags |= FLAG_MASK_INTERNAL;
134 }
135#endif
136 }
137
138 break;
139 case AttributeName.RuntimeVisibleTypeAnnotations:
140 if (classFile.MajorVersion < 52)
141 goto default;
142
143 var _runtimeVisibleTypeAnnotations = (IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute;
144 classFile.CreateUtf8ConstantPoolItems(utf8_cp);
145 runtimeVisibleTypeAnnotations = _runtimeVisibleTypeAnnotations.TypeAnnotations;
146 break;
147 default:
148 break;
149 }
150 }
151
152 }
153
154 private void DecodePropertyAnnotation(ClassFile classFile, object[] annot)
155 {
156 if (propertyGetterSetter != null)
157 {
158 classFile.diagnostics.GenericClassLoadingError($"Ignoring duplicate ikvm.lang.Property annotation on {classFile.Name}.{this.Name}");
159 return;
160 }
161
162 propertyGetterSetter = new string[2];
163 for (int i = 2; i < annot.Length - 1; i += 2)
164 {
165 string value = annot[i + 1] as string;
166 if (value == null)
167 {
168 propertyGetterSetter = null;
169 break;
170 }
171 if (annot[i].Equals("get") && propertyGetterSetter[0] == null)
172 {
173 propertyGetterSetter[0] = value;
174 }
175 else if (annot[i].Equals("set") && propertyGetterSetter[1] == null)
176 {
177 propertyGetterSetter[1] = value;
178 }
179 else
180 {
181 propertyGetterSetter = null;
182 break;
183 }
184 }
185
186 if (propertyGetterSetter == null || propertyGetterSetter[0] == null)
187 {
188 propertyGetterSetter = null;
189 classFile.diagnostics.GenericClassLoadingError($"Ignoring malformed ikvm.lang.Property annotation on {classFile.Name}.{Name}");
190 return;
191 }
192 }
193
194 protected override void ValidateSig(ClassFile classFile, string descriptor)
195 {
196 if (!IsValidFieldDescriptor(descriptor))
197 throw new ClassFormatError("{0} (Field \"{1}\" has invalid signature \"{2}\")", classFile.Name, this.Name, descriptor);
198 }
199
200 internal object ConstantValue => constantValue;
201
202 internal void PatchConstantValue(object value) => constantValue = value;
203
204 internal bool IsStaticFinalConstant => (accessFlags & (Modifiers.Final | Modifiers.Static)) == (Modifiers.Final | Modifiers.Static) && constantValue != null;
205
206 internal bool IsProperty => propertyGetterSetter != null;
207
208 internal string PropertyGetter => propertyGetterSetter[0];
209
210 internal string PropertySetter => propertyGetterSetter[1];
211
212 }
213
214 }
215
216}
global::java.lang.invoke.LambdaForm.Name Name
static bool IsValidFieldDescriptor(string descriptor)
Returns true if the specified descriptor is a valid field descriptor.
Definition ClassFile.cs:152