예제 #1
0
        public static ClassNode ParseClass(Stream stream)
        {
            var state  = new ClassReaderState();
            var result = new ClassNode();

            state.ClassNode = result;

            if (Binary.BigEndian.ReadUInt32(stream) != Magic)
            {
                throw new IOException("Wrong magic in class");
            }

            result.MinorVersion = Binary.BigEndian.ReadUInt16(stream);
            result.MajorVersion = (ClassVersion)Binary.BigEndian.ReadUInt16(stream);

            if (result.MajorVersion > ClassVersion.Java8)
            {
                throw new Exception($"Wrong Java version: {result.MajorVersion}");
            }

            var constantPool = new ConstantPool();

            constantPool.Read(stream);
            state.ConstantPool = constantPool;

            result.Access = (ClassAccessModifiers)Binary.BigEndian.ReadUInt16(stream);

            result.Name      = new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String);
            result.SuperName = new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String);

            var interfacesCount = Binary.BigEndian.ReadUInt16(stream);

            result.Interfaces.Capacity = interfacesCount;
            for (var i = 0; i < interfacesCount; i++)
            {
                result.Interfaces.Add(new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String));
            }

            var fieldsCount = Binary.BigEndian.ReadUInt16(stream);

            result.Fields.Capacity = fieldsCount;
            for (var i = 0; i < fieldsCount; i++)
            {
                result.Fields.Add(ParseField(stream, state));
            }

            var methodsCount = Binary.BigEndian.ReadUInt16(stream);

            result.Methods.Capacity = methodsCount;
            for (var i = 0; i < methodsCount; i++)
            {
                result.Methods.Add(ParseMethod(stream, state));
            }

            var attributesCount = Binary.BigEndian.ReadUInt16(stream);

            result.Attributes.Capacity = attributesCount;
            for (var i = 0; i < attributesCount; i++)
            {
                result.Attributes.Add(ParseAttribute(stream, state, AttributeScope.Class));
            }

            result.Parse(state);

            return(result);
        }
예제 #2
0
        public static void WriteClass(Stream stream, ClassNode classNode)
        {
            Binary.BigEndian.Write(stream, Magic);
            Binary.BigEndian.Write(stream, classNode.MinorVersion);
            Binary.BigEndian.Write(stream, (ushort)classNode.MajorVersion);
            var afterConstantPoolDataStream = new MemoryStream();
            var constantPool = new ConstantPool();
            var state        = new ClassWriterState
            {
                ClassNode    = classNode,
                ConstantPool = constantPool
            };

            classNode.Save(state);

            Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Access);
            Binary.BigEndian.Write(afterConstantPoolDataStream,
                                   constantPool.Find(new ClassEntry(new Utf8Entry(classNode.Name.Name))));
            Binary.BigEndian.Write(afterConstantPoolDataStream,
                                   constantPool.Find(new ClassEntry(new Utf8Entry(classNode.SuperName.Name))));

            if (classNode.Interfaces.Count > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(classNode.Interfaces.Count), $"Too many interfaces: {classNode.Interfaces.Count} > {ushort.MaxValue}");
            }
            Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Interfaces.Count);
            foreach (var interfaceClassName in classNode.Interfaces)
            {
                Binary.BigEndian.Write(afterConstantPoolDataStream,
                                       constantPool.Find(new ClassEntry(new Utf8Entry(interfaceClassName.Name))));
            }

            if (classNode.Fields.Count > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(classNode.Fields.Count), $"Too many fields: {classNode.Fields.Count} > {ushort.MaxValue}");
            }
            Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Fields.Count);
            foreach (var field in classNode.Fields)
            {
                WriteField(afterConstantPoolDataStream, field, state);
            }

            if (classNode.Methods.Count > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(classNode.Methods.Count), $"Too many methods: {classNode.Methods.Count} > {ushort.MaxValue}");
            }
            Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Methods.Count);
            foreach (var method in classNode.Methods)
            {
                WriteMethod(afterConstantPoolDataStream, method, state);
            }

            if (classNode.Attributes.Count > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(classNode.Attributes.Count), $"Too many attributes: {classNode.Attributes.Count} > {ushort.MaxValue}");
            }
            Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Attributes.Count);
            foreach (var attriute in classNode.Attributes)
            {
                WriteAttribute(afterConstantPoolDataStream, attriute, state, AttributeScope.Class);
            }

            constantPool.Write(stream);
            stream.Write(afterConstantPoolDataStream.ToArray());
        }