IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ClassFile.ConstantPoolItemClass.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.ByteCode.Decoding;
27
28namespace IKVM.Runtime
29{
30
31 sealed partial class ClassFile
32 {
33
37 internal sealed class ConstantPoolItemClass : ConstantPoolItem, IEquatable<ConstantPoolItemClass>
38 {
39
40 static readonly char[] InvalidJava15Characters = ['.', ';', '[', ']'];
41
42 readonly ClassConstantData _data;
43 string _name;
44 RuntimeJavaType _javaType;
45
52 public ConstantPoolItemClass(RuntimeContext context, ClassConstantData data) :
53 base(context)
54 {
55 _data = data;
56 }
57
64 public ConstantPoolItemClass(RuntimeContext context, string name, RuntimeJavaType javaType) :
65 base(context)
66 {
67 _name = name;
68 _javaType = javaType;
69 }
70
72 public override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
73 {
74 // if the item was patched, we already have a name
75 if (_name != null)
76 return;
77
78 _name = classFile.GetConstantPoolUtf8String(utf8_cp, _data.Name);
79 if (_name.Length > 0)
80 {
81 // We don't enforce the strict class name rules in the static compiler, since HotSpot doesn't enforce *any* rules on
82 // class names for the system (and boot) class loader. We still need to enforce the 1.5 restrictions, because we
83 // rely on those invariants.
84#if !IMPORTER
85 if (classFile.MajorVersion < 49 && (options & ClassFileParseOptions.RelaxedClassNameValidation) == 0)
86 {
87 var prev = _name[0];
88 if (char.IsLetter(prev) || prev == '$' || prev == '_' || prev == '[' || prev == '/')
89 {
90 int skip = 1;
91 int end = _name.Length;
92 if (prev == '[')
93 {
94 if (!IsValidFieldDescriptor(_name))
95 throw new ClassFormatError("Invalid class name \"{0}\"", _name);
96
97 while (_name[skip] == '[')
98 skip++;
99
100 if (_name.EndsWith(";"))
101 end--;
102 }
103
104 for (int i = skip; i < end; i++)
105 {
106 var c = _name[i];
107 if (!char.IsLetterOrDigit(c) && c != '$' && c != '_' && (c != '/' || prev == '/'))
108 throw new ClassFormatError("Invalid class name \"{0}\"", _name);
109
110 prev = c;
111 }
112
113 _name = string.Intern(_name.Replace('/', '.'));
114 return;
115 }
116 }
117 else
118#endif
119 {
120 // since 1.5 the restrictions on class names have been greatly reduced
121 int start = 0;
122 int end = _name.Length;
123 if (_name[0] == '[')
124 {
125 if (!IsValidFieldDescriptor(_name))
126 throw new ClassFormatError("Invalid class name \"{0}\"", _name);
127
128 // the semicolon is only allowed at the end and IsValidFieldSig enforces this,
129 // but since invalidJava15Characters contains the semicolon, we decrement end
130 // to make the following check against invalidJava15Characters ignore the
131 // trailing semicolon.
132 if (_name[end - 1] == ';')
133 end--;
134
135 while (_name[start] == '[')
136 start++;
137 }
138
139 if (_name.IndexOfAny(InvalidJava15Characters, start, end - start) >= 0)
140 throw new ClassFormatError("Invalid class name \"{0}\"", _name);
141
142 _name = string.Intern(_name.Replace('/', '.'));
143 return;
144 }
145 }
146 }
147
149 public override void MarkLinkRequired()
150 {
151 _javaType ??= Context.VerifierJavaTypeFactory.Null;
152 }
153
154 internal void LinkSelf(RuntimeJavaType thisType)
155 {
156 _javaType = thisType;
157 }
158
160 public override void Link(RuntimeJavaType thisType, LoadMode mode)
161 {
162 if (_javaType == Context.VerifierJavaTypeFactory.Null)
163 {
164 var tw = thisType.ClassLoader.LoadClass(_name, mode | LoadMode.WarnClassNotFound);
165
166#if IMPORTER == false && FIRST_PASS == false
167 if (!tw.IsUnloadable)
168 {
169 try
170 {
171 thisType.ClassLoader.CheckPackageAccess(tw, thisType.ClassObject.pd);
172 }
173 catch (java.lang.SecurityException)
174 {
175 tw = new RuntimeUnloadableJavaType(Context, _name);
176 }
177 }
178#endif
179
180 _javaType = tw;
181 }
182 }
183
187 public string Name => _name;
188
193 public RuntimeJavaType GetClassType()
194 {
195 return _javaType;
196 }
197
199 public override ConstantType GetConstantType()
200 {
201 return ConstantType.Class;
202 }
203
209 public bool Equals(ConstantPoolItemClass other)
210 {
211 return ReferenceEquals(_name, other._name);
212 }
213
215 public sealed override int GetHashCode()
216 {
217 return _name.GetHashCode();
218 }
219
220 }
221
222 }
223
224}
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
RuntimeVerifierJavaTypeFactory VerifierJavaTypeFactory
Gets the RuntimeVerifierJavaTypeFactory associated with this instance of the runtime.