All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.packenius.datadivider.javaclass.ConstantPool Maven / Gradle / Ivy

package com.packenius.datadivider.javaclass;

import java.util.ArrayList;
import java.util.List;

import com.packenius.datadivider.javaclass.cp.ConstantPoolEntry;
import com.packenius.datadivider.javaclass.cp.ConstantPoolEntryWithMethodRef;
import com.packenius.datadivider.javaclass.cp.CpClass;
import com.packenius.datadivider.javaclass.cp.CpDouble;
import com.packenius.datadivider.javaclass.cp.CpFieldRef;
import com.packenius.datadivider.javaclass.cp.CpFloat;
import com.packenius.datadivider.javaclass.cp.CpInteger;
import com.packenius.datadivider.javaclass.cp.CpInterfaceMethodRef;
import com.packenius.datadivider.javaclass.cp.CpInvokeDynamic;
import com.packenius.datadivider.javaclass.cp.CpLong;
import com.packenius.datadivider.javaclass.cp.CpMethodHandle;
import com.packenius.datadivider.javaclass.cp.CpMethodRef;
import com.packenius.datadivider.javaclass.cp.CpMethodType;
import com.packenius.datadivider.javaclass.cp.CpNameAndType;
import com.packenius.datadivider.javaclass.cp.CpString;
import com.packenius.datadivider.javaclass.cp.CpUtf8;
import com.packenius.dumpapi.DumpBlock;
import com.packenius.dumpapi.DumpReader;

/**
 * Konstantenpool einer Klasse.
 * @author Christian Packenius, 2016.
 */
public class ConstantPool extends DumpBlock {
    /**
     * Sämtliche Einträge des Konstantenpools.
     */
    private final List content = new ArrayList<>();

    /**
     * Konstruktor.
     */
    public ConstantPool(DumpReader reader) {
        super(reader);

        // Das Objekt mit dem Index 0 ist immer null.
        content.add(null);

        // Konstantenpool im ersten Schritt einlesen.
        // Mag ungewöhnlich sein, aber wir beginnen bei Eintrag 1, nicht 0.
        int constantPoolCount = reader.readBigEndianU2("Entries count: ##DEC##").value;
        while (content.size() < constantPoolCount) {
            ConstantPoolEntry cpEntry = readNextEntry(reader, content.size());
            add(cpEntry);
        }

        setEndAddress(reader);
    }

    /**
     * Fügt dem Konstantenpool einen neuen Eintrag hinzu.
     * @param cpEntry Neuer CP-Eintrag.
     * @return ID des CP-Eintrages.
     */
    private int add(ConstantPoolEntry cpEntry) {
        int id = content.size();

        content.add(cpEntry);

        // Long- und Double-Einträge werden idiotischerweise gedoppelt.
        if (cpEntry instanceof CpDouble || cpEntry instanceof CpLong) {
            content.add(cpEntry);
        }

        return id;
    }

    /**
     * Liest den nächsten Eintrag aus dem Konstantenpool.
     * @param cpID Nummer innerhalb des Konstantenpools (ab 1 aufsteigend, bei Long
     * und Double zwei Nummern).
     */
    private ConstantPoolEntry readNextEntry(DumpReader reader, int cpID) {
        // Vorab das Tag lesen, damit wir wissen, welche Art von CP-Eintrag wir
        // lesen müssen.
        short tag = reader.readU1("Tag id: ##DEC##").value;
        reader.deltaIndex(-1);

        switch (tag) {
        case 1:
            return new CpUtf8(reader, cpID, this);
        case 3:
            return new CpInteger(reader, cpID);
        case 4:
            return new CpFloat(reader, cpID);
        case 5:
            return new CpLong(reader, cpID);
        case 6:
            return new CpDouble(reader, cpID);
        case 7:
            return new CpClass(reader, cpID);
        case 8:
            return new CpString(reader, cpID, this);
        case 9:
            return new CpFieldRef(reader, cpID, this);
        case 10:
            return new CpMethodRef(reader, cpID, this);
        case 11:
            return new CpInterfaceMethodRef(reader, cpID, this);
        case 12:
            return new CpNameAndType(reader, cpID);
        case 15:
            return new CpMethodHandle(reader, cpID, this);
        case 16:
            return new CpMethodType(reader, cpID, this);
        case 18:
            return new CpInvokeDynamic(reader, cpID, this);
        default:
            throw new IllegalArgumentException("Eintrag unbekannten Typs [" + tag + "] im Konstantenpool!");
        }
    }

    /**
     * Ermittelt einen beliebigen Eintrag aus dem Konstantenpool.
     * @param index Index des Eintrags.
     * @return Eigentlicher Eintrag.
     */
    public ConstantPoolEntry getEntry(int index) {
        return content.get(index);
    }

    /**
     * Ermittelt einen UTF8-Eintrag.
     * @param index Index auf den gewünschten Eintrag.
     * @return Geforderter UTF8-Eintrag.
     */
    public CpUtf8 getUtf8Entry(int index) {
        return content.get(index).asUtf8();
    }

    /**
     * Ermittelt einen Class-Eintrag.
     * @param index Index auf den gewünschten Eintrag.
     * @return Geforderter Class-Eintrag.
     */
    public CpClass getClassEntry(int index) {
        return (CpClass) content.get(index);
    }

    /**
     * Ermittelt einen NameAndType-Eintrag.
     * @param index Index auf den gewünschten Eintrag.
     * @return Geforderter NameAndType-Eintrag.
     */
    public CpNameAndType getNameAndTypeEntry(int index) {
        return (CpNameAndType) content.get(index);
    }

    /**
     * Ermittelt einen InterfaceMethod-Eintrag.
     * @param index Index auf den gewünschten Eintrag.
     * @return Geforderter InterfaceMethod-Eintrag.
     */
    public CpInterfaceMethodRef getInterfaceMethodEntry(int index) {
        return (CpInterfaceMethodRef) content.get(index);
    }

    /**
     * @param index
     * @return MethodRef oder InterfaceMethodRef.
     */
    public ConstantPoolEntryWithMethodRef getEntryWithMethodRef(int index) {
        return (ConstantPoolEntryWithMethodRef) content.get(index);
    }

    public CpFieldRef getFieldRefEntry(int index) {
        return (CpFieldRef) content.get(index);
    }

    public ConstantPoolEntryWithMethodRef getMethodRefEntry(int index) {
        return (ConstantPoolEntryWithMethodRef) content.get(index);
    }

    @Override
    public String toString() {
        return "Constant Pool [" + content.size() + " entries]";
    }

    @Override
    public String getDescription() {
        return "Constant pool of this java class file, containing all types of constants used within the class file. Each entry in " //
                + "the constant pool table must begin with a 1-byte tag indicating " //
                + "the kind of constant denoted by the entry.\r\nHINT:\r\nIndex #0 is never used, for this the count is +1 larger than the real number of entries.";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy