
com.tangosol.dev.assembler.Method Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.dev.assembler;
import com.tangosol.util.NullImplementation;
import com.tangosol.util.StringTable;
import java.io.IOException;
import java.io.DataInput;
import java.io.DataOutput;
import java.util.Enumeration;
import java.util.Vector;
/**
* Represents a Java Virtual Machine Method structure as defined by the Java
* Virtual Machine (JVM) Specification.
*
* @version 0.50, 05/14/98, assembler/dis-assembler
* @author Cameron Purdy
*/
public class Method extends VMStructure implements Constants
{
// ----- construction ---------------------------------------------------
/**
* Construct a method structure. Used by ClassFile disassembly.
*
* @param sClass the class name containing this method
* @param fInterface whether this method is defined on an interface
*/
protected Method(String sClass, boolean fInterface)
{
m_sClass = sClass;
f_fInterface = fInterface;
}
/**
* Construct a method structure.
*
* @param sName the method name
* @param sSig the method signature
* @param fInterface whether this method is defined on an interface
*/
protected Method(String sName, String sSig, boolean fInterface)
{
this(new UtfConstant(sName), new UtfConstant(sSig.replace('.','/')), fInterface);
}
/**
* Construct a method which references the passed UTF constants.
*
* @param constantName the referenced UTF constant which contains the
* name of the method
* @param constantSig the referenced UTF constant which contains the
* method signature
* @param fInterface whether this method is defined on an interface
*/
protected Method(UtfConstant constantName, UtfConstant constantSig, boolean fInterface)
{
if (constantName == null || constantSig == null)
{
throw new IllegalArgumentException(CLASS + ": Values cannot be null!");
}
m_utfName = constantName;
m_utfSig = constantSig;
f_fInterface = fInterface;
}
// ----- VMStructure operations -----------------------------------------
/**
* The disassembly process reads the structure from the passed input
* stream and uses the constant pool to dereference any constant
* references.
*
* @param stream the stream implementing java.io.DataInput from which
* to read the assembled VM structure
* @param pool the constant pool for the class which contains any
* constants referenced by this VM structure
*/
protected void disassemble(DataInput stream, ConstantPool pool)
throws IOException
{
// access flags
m_flags.disassemble(stream, pool);
// name and signature
m_utfName = (UtfConstant) pool.getConstant(stream.readUnsignedShort());
m_utfSig = (UtfConstant) pool.getConstant(stream.readUnsignedShort());
// attributes
m_tblAttribute.clear();
int cAttr = stream.readUnsignedShort();
for (int i = 0; i < cAttr; ++i)
{
Attribute attr = Attribute.loadAttribute(this, stream, pool);
m_tblAttribute.put(attr.getIdentity(), attr);
}
}
/**
* The pre-assembly step collects the necessary entries for the constant
* pool. During this step, all constants used by this VM structure and
* any sub-structures are registered with (but not yet bound by position
* in) the constant pool.
*
* @param pool the constant pool for the class which needs to be
* populated with the constants required to build this
* VM structure
*/
protected void preassemble(ConstantPool pool)
{
pool.registerConstant(m_utfName);
pool.registerConstant(m_utfSig );
m_flags.preassemble(pool);
Enumeration enmr = m_tblAttribute.elements();
while (enmr.hasMoreElements())
{
Attribute attr = (Attribute) enmr.nextElement();
try
{
attr.preassemble(pool);
}
catch (Throwable e)
{
if (attr.getName().equals(ATTR_CODE))
{
out("Code pre-assembly error in: " + toString());
((CodeAttribute) attr).print();
}
if (e instanceof RuntimeException)
{
throw (RuntimeException) e;
}
else
{
throw (Error) e;
}
}
}
}
/**
* The assembly process assembles and writes the structure to the passed
* output stream, resolving any dependencies using the passed constant
* pool.
*
* @param stream the stream implementing java.io.DataOutput to which to
* write the assembled VM structure
* @param pool the constant pool for the class which by this point
* contains the entire set of constants required to build
* this VM structure
*/
protected void assemble(DataOutput stream, ConstantPool pool)
throws IOException
{
m_flags.assemble(stream, pool);
stream.writeShort(pool.findConstant(m_utfName));
stream.writeShort(pool.findConstant(m_utfSig ));
stream.writeShort(m_tblAttribute.getSize());
Enumeration enmr = m_tblAttribute.elements();
while (enmr.hasMoreElements())
{
Attribute attr = (Attribute) enmr.nextElement();
try
{
attr.assemble(stream, pool);
}
catch (Throwable e)
{
if (attr.getName().equals(ATTR_CODE))
{
out("Code assembly error in: " + toString());
((CodeAttribute) attr).print();
}
if (e instanceof RuntimeException)
{
throw (RuntimeException) e;
}
else
{
throw (Error) e;
}
}
}
}
/**
* Determine the identity of the VM structure (if applicable).
*
* @return the string identity of the VM structure
*/
public String getIdentity()
{
return m_utfName.getValue() + m_utfSig.getValue();
}
/**
* Determine if the VM structure (or any contained VM structure) has been
* modified.
*
* @return true if the VM structure has been modified
*/
public boolean isModified()
{
if (m_fModified || m_flags.isModified())
{
return true;
}
Enumeration enmr = m_tblAttribute.elements();
while (enmr.hasMoreElements())
{
Attribute attr = (Attribute) enmr.nextElement();
if (attr.isModified())
{
return true;
}
}
return false;
}
/**
* Reset the modified state of the VM structure.
*/
protected void resetModified()
{
m_flags.resetModified();
Enumeration enmr = m_tblAttribute.elements();
while (enmr.hasMoreElements())
{
((Attribute) enmr.nextElement()).resetModified();
}
m_fModified = false;
}
// ----- Comparable operations ------------------------------------------
/**
* Compares this Object with the specified Object for order. Returns a
* negative integer, zero, or a positive integer as this Object is less
* than, equal to, or greater than the given Object.
*
* @param obj the Object
to be compared.
*
* @return a negative integer, zero, or a positive integer as this Object
* is less than, equal to, or greater than the given Object.
*
* @exception ClassCastException the specified Object's type prevents it
* from being compared to this Object.
*/
public int compareTo(Object obj)
{
Method that = (Method) obj;
int nResult = this.m_utfName.compareTo(that.m_utfName);
if (nResult == 0)
{
nResult = this.m_utfSig.compareTo(that.m_utfSig);
}
return nResult;
}
// ----- Object operations ----------------------------------------------
/**
* Produce a human-readable string describing the method.
*
* @return a string describing the method
*/
public String toString()
{
String sMods = m_flags.toString(ACC_METHOD);
String sName = m_utfName.getValue();
String[] asType = toTypeStrings(m_utfSig.getValue());
int cType = asType.length;
StringBuffer sb = new StringBuffer();
if (sMods.length() > 0)
{
sb.append(sMods)
.append(' ');
}
sb.append(asType[0])
.append(' ')
.append(sName)
.append('(');
for (int i = 1; i < cType; ++i)
{
if (i > 1)
{
sb.append(", ");
}
sb.append(asType[i]);
}
sb.append(')');
return sb.toString();
}
/**
* Compare this object to another object for equality.
*
* @param obj the other object to compare to this
*
* @return true if this object equals that object
*/
public boolean equals(Object obj)
{
try
{
Method that = (Method) obj;
return this == that
|| this.getClass() == that.getClass()
&& this.m_utfName .equals(that.m_utfName )
&& this.m_utfSig .equals(that.m_utfSig )
&& this.m_flags .equals(that.m_flags )
&& this.m_tblAttribute.equals(that.m_tblAttribute);
}
catch (NullPointerException e)
{
// obj is null
return false;
}
catch (ClassCastException e)
{
// obj is not of this class
return false;
}
}
// ----- Method operations ----------------------------------------------
/**
* Add a description (name and access flags) to a parameter at index
* {@code iParam} in the method signature.
*
* Access flags is restricted to the following bit values:
*
* - {@link MethodParametersAttribute.MethodParameter#ACC_FINAL final}
* - {@link MethodParametersAttribute.MethodParameter#ACC_SYNTHETIC synthetic}
* - {@link MethodParametersAttribute.MethodParameter#ACC_MANDATED mandated}
*
*
* @param iParam an index to the parameter in the method signature
* @param sName the name of the parameter
* @param nFlags the access flags for the parameter; bit-mask of the following
* bits: {@link MethodParametersAttribute.MethodParameter#ACC_FINAL final},
* {@link MethodParametersAttribute.MethodParameter#ACC_SYNTHETIC synthetic},
* {@link MethodParametersAttribute.MethodParameter#ACC_MANDATED mandated}
*
* @return whether the parameter description was added
*/
public boolean addParameter(int iParam, String sName, int nFlags)
{
String[] asTypes = getTypes();
int cParams = asTypes.length - 1;
if (iParam > cParams)
{
return false;
}
MethodParametersAttribute attrParams = ensureMethodParameters(cParams);
return attrParams.addParameter(iParam, sName, nFlags);
}
/**
* Parse the method signature into discrete return type and parameter
* signatures as they would appear in Java source.
*
* @param sSig the JVM method signature
*
* @return an array of Java type strings, where [0] is the return
* type and [1]..[c] are the parameter types.
*/
public static String[] toTypeStrings(String sSig)
{
String[] asType = toTypes(sSig);
int cTypes = asType.length;
for (int i = 0; i < cTypes; ++i)
{
asType[i] = Field.toTypeString(asType[i]);
}
return asType;
}
/**
* Parse the method signature into discrete return type and parameter
* signatures as they appear in Java .class structures.
*
* @param sSig the JVM method signature
*
* @return an array of JVM type signatures, where [0] is the return
* type and [1]..[c] are the parameter types.
*/
public static String[] toTypes(String sSig)
{
// check for start of signature
char[] ach = sSig.toCharArray();
if (ach[0] != '(')
{
throw new IllegalArgumentException("JVM Method Signature must start with '('");
}
// reserve the first element for the return value
Vector vect = new Vector();
vect.addElement(null);
// parse parameter signatures
int of = 1;
while (ach[of] != ')')
{
int cch = getTypeLength(ach, of);
vect.addElement(new String(ach, of, cch));
of += cch;
}
// return value starts after the parameter-stop character
// and runs to the end of the method signature
++of;
vect.setElementAt(new String(ach, of, ach.length - of), 0);
String[] asSig = new String[vect.size()];
vect.copyInto(asSig);
return asSig;
}
private static int getTypeLength(char[] ach, int of)
{
switch (ach[of])
{
case 'V':
case 'Z':
case 'B':
case 'C':
case 'S':
case 'I':
case 'J':
case 'F':
case 'D':
return 1;
case '[':
{
int cch = 1;
while (isDecimal(ach[++of]))
{
++cch;
}
return cch + getTypeLength(ach, of);
}
case 'L':
{
int cch = 2;
while (ach[++of] != ';')
{
++cch;
}
return cch;
}
default:
throw new IllegalArgumentException("JVM Type Signature cannot start with '" + ach[of] + "'");
}
}
// ----- accessors: name and type --------------------------------------
/**
* Get the name of the method as a string.
*
* @return the method name
*/
public String getName()
{
return m_utfName.getValue();
}
/**
* Get the signature of the method as a string. (This is not called
* "getSignature" because that could imply a "SignatureConstant", which
* is itself both name and type.)
*
* @return the method signature
*/
public String getType()
{
return m_utfSig.getValue();
}
/**
* Get the types of the method parameters and return value as they would
* appear in JVM .class structures.
*
* @return an array of JVM type signatures, [0] for the return value type
* and [1..n] for the parameter types
*/
public String[] getTypes()
{
return toTypes(m_utfSig.getValue());
}
/**
* Get the types of the method parameters and return value as they would
* appear in Java source.
*
* @return an array of strings, [0] for the return value type and [1..n]
* for the parameter types
*/
public String[] getTypeStrings()
{
return toTypeStrings(m_utfSig.getValue());
}
/**
* Get the names of the method parameters as they appear in source code.
* This only works for code which has been assembled or disassembled,
* not for code which has been created but not yet assembled.
*
* @return an array of parameter names, [0] for the return value and
* [1..n] for the parameters; the return value name is always
* null and the other names are null if debugging information
* is not available
*/
public String[] getNames()
{
String[] as = getTypes();
int c = as.length;
CodeAttribute code = (CodeAttribute) m_tblAttribute.get(ATTR_CODE);
if (code != null)
{
LocalVariableTableAttribute vars =
(LocalVariableTableAttribute) code.getAttribute(ATTR_VARIABLES);
if (vars != null)
{
int cwBase = isStatic() ? 0 : 1;
int cwParams = cwBase;
for (int i = 1; i < c; ++i)
{
switch (as[i].charAt(0))
{
default:
cwParams += 1;
break;
case 'D':
case 'J':
cwParams += 2;
break;
}
}
int[] aiSlotToParam = new int[cwParams];
cwParams = cwBase;
for (int i = 1; i < c; ++i)
{
// the slot number (cwParams) corresponds to the 1-based
// parameter number (i)
aiSlotToParam[cwParams] = i;
switch (as[i].charAt(0))
{
default:
cwParams += 1;
break;
case 'D':
case 'J':
cwParams += 2;
break;
}
// clear param type
as[i] = null;
}
// clear return type
as[0] = null;
for (Enumeration enmr = vars.ranges(); enmr.hasMoreElements(); )
{
AbstractLocalVariableTableAttribute.Range range =
(AbstractLocalVariableTableAttribute.Range) enmr.nextElement();
if (range.getSlot() < cwParams)
{
int i = aiSlotToParam[range.getSlot()];
if (i > 0 && as[i] == null)
{
as[i] = range.getVariableName();
}
}
}
return as;
}
}
// clear names
for (int i = 0; i < c; ++i)
{
as[i] = null;
}
return as;
}
/**
* Get the UTF constant which holds the method name.
*
* @return the UTF constant which contains the name
*/
public UtfConstant getNameConstant()
{
return m_utfName;
}
/**
* Get the UTF constant which holds the method signature.
*
* @return the UTF constant which contains the signature
*/
public UtfConstant getTypeConstant()
{
return m_utfSig;
}
// ----- accessor: access ----------------------------------------------
/**
* Get the method accessibility value.
*
* @return one of ACC_PUBLIC, ACC_PROTECTED, ACC_PRIVATE, or ACC_PACKAGE
*/
public int getAccess()
{
return m_flags.getAccess();
}
/**
* Set the method accessibility value.
*
* @param nAccess should be one of ACC_PUBLIC, ACC_PROTECTED,
* ACC_PRIVATE, or ACC_PACKAGE
*/
public void setAccess(int nAccess)
{
m_flags.setAccess(nAccess);
}
/**
* Determine if the accessibility is public.
*
* @return true if the accessibility is public
*/
public boolean isPublic()
{
return m_flags.isPublic();
}
/**
* Set the accessibility to public.
*/
public void setPublic()
{
m_flags.setPublic();
}
/**
* Determine if the accessibility is protected.
*
* @return true if the accessibility is protected
*/
public boolean isProtected()
{
return m_flags.isProtected();
}
/**
* Set the accessibility to protected.
*/
public void setProtected()
{
m_flags.setProtected();
}
/**
* Determine if the accessibility is package private.
*
* @return true if the accessibility is package private
*/
public boolean isPackage()
{
return m_flags.isPackage();
}
/**
* Set the accessibility to package private.
*/
public void setPackage()
{
m_flags.setPackage();
}
/**
* Determine if the accessibility is private.
*
* @return true if the accessibility is private
*/
public boolean isPrivate()
{
return m_flags.isPrivate();
}
/**
* Set the accessibility to private.
*/
public void setPrivate()
{
m_flags.setPrivate();
}
// ----- accessor: static -------------------------------------------
/**
* Determine if the Static attribute is set.
*
* @return true if Static
*/
public boolean isStatic()
{
return m_flags.isStatic();
}
/**
* Set the Static attribute.
*
* @param fStatic true to set to Static, false otherwise
*/
public void setStatic(boolean fStatic)
{
m_flags.setStatic(fStatic);
}
// ----- accessor: final -------------------------------------------
/**
* Determine if the Final attribute is set.
*
* @return true if Final
*/
public boolean isFinal()
{
return m_flags.isFinal();
}
/**
* Set the Final attribute.
*
* @param fFinal true to set to Final, false otherwise
*/
public void setFinal(boolean fFinal)
{
m_flags.setFinal(fFinal);
}
// ----- accessor: synchronized -------------------------------------------
/**
* Determine if the synchronized attribute is set.
*
* @return true if synchronized
*/
public boolean isSynchronized()
{
return m_flags.isSynchronized();
}
/**
* Set the synchronized attribute.
*
* @param fSynchronized true to set to synchronized, false otherwise
*/
public void setSynchronized(boolean fSynchronized)
{
m_flags.setSynchronized(fSynchronized);
}
// ----- accessor: native -------------------------------------------
/**
* Determine if the native attribute is set.
*
* @return true if native
*/
public boolean isNative()
{
return m_flags.isNative();
}
/**
* Set the native attribute.
*
* @param fNative true to set to native, false otherwise
*/
public void setNative(boolean fNative)
{
m_flags.setNative(fNative);
}
// ----- accessor: abstract -------------------------------------------
/**
* Determine if the abstract attribute is set.
*
* @return true if abstract
*/
public boolean isAbstract()
{
return m_flags.isAbstract();
}
/**
* Set the abstract attribute.
*
* @param fAbstract true to set to abstract, false otherwise
*/
public void setAbstract(boolean fAbstract)
{
m_flags.setAbstract(fAbstract);
}
// ----- accessor: bridge ----------------------------------------------
/**
* Determine if the bridge attribute is set.
*
* @return true if bridge
*/
public boolean isBridge()
{
return m_flags.isBridge();
}
/**
* Set the bridge attribute.
*
* @param fBridge true to set to bridge, false otherwise
*/
public void setBridge(boolean fBridge)
{
m_flags.setBridge(fBridge);
}
// ----- accessor: varargs ---------------------------------------------
/**
* Determine if the varargs attribute is set.
*
* @return true if varargs
*/
public boolean isVarArgs()
{
return m_flags.isVarArgs();
}
/**
* Set the varargs attribute.
*
* @param fVarArgs true to set to varargs, false otherwise
*/
public void setVarArgs(boolean fVarArgs)
{
m_flags.setVarArgs(fVarArgs);
}
// ----- accessor: strict ----------------------------------------------
/**
* Determine if the strict attribute is set.
*
* @return true if strict
*/
public boolean isStrict()
{
return m_flags.isStrict();
}
/**
* Set the strict attribute.
*
* @param fStrict true to set to strict, false otherwise
*/
public void setStrict(boolean fStrict)
{
m_flags.setStrict(fStrict);
}
// ----- accessor: attribute -------------------------------------------
/**
* Access a Java .class attribute structure.
*
* @param sName the attribute name
*
* @return the specified attribute or null if the attribute does not exist
*/
public Attribute getAttribute(String sName)
{
return (Attribute) m_tblAttribute.get(sName);
}
/**
* Add a Java .class attribute structure.
*
* @param sName the attribute name
*
* @return the new attribute
*/
public Attribute addAttribute(String sName)
{
Attribute attribute;
if (sName.equals(ATTR_CODE))
{
attribute = new CodeAttribute(this);
}
else if (sName.equals(ATTR_EXCEPTIONS))
{
attribute = new ExceptionsAttribute(this);
}
else if (sName.equals(ATTR_DEPRECATED))
{
attribute = new DeprecatedAttribute(this);
}
else if (sName.equals(ATTR_SYNTHETIC))
{
attribute = new SyntheticAttribute(this);
}
else if (sName.equals(ATTR_SIGNATURE))
{
attribute = new SignatureAttribute(this);
}
else if (sName.equals(ATTR_RTVISANNOT))
{
attribute = new RuntimeVisibleAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_RTINVISANNOT))
{
attribute = new RuntimeInvisibleAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_RTVISPARAMANNOT))
{
attribute = new RuntimeVisibleParameterAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_RTINVISPARAMANNOT))
{
attribute = new RuntimeInvisibleParameterAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_RTVISTANNOT))
{
attribute = new RuntimeVisibleTypeAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_RTINVISTANNOT))
{
attribute = new RuntimeInvisibleTypeAnnotationsAttribute(this);
}
else if (sName.equals(ATTR_METHODPARAMS))
{
attribute = new MethodParametersAttribute(this);
}
else
{
attribute = new Attribute(this, sName);
}
m_tblAttribute.put(attribute.getIdentity(), attribute);
m_fModified = true;
return attribute;
}
/**
* Remove a attribute.
*
* @param sName the attribute name
*/
public void removeAttribute(String sName)
{
m_tblAttribute.remove(sName);
m_fModified = true;
}
/**
* Access the set of attributes.
*
* @return an enumeration of attributes (not attribute names)
*/
public Enumeration getAttributes()
{
return m_tblAttribute.elements();
}
// ----- accessor: attribute helpers -----------------------------------
/**
* Get the code attribute.
*
* @return the code attribute, creating one if necessary
*/
public CodeAttribute getCode()
{
CodeAttribute attr = (CodeAttribute) m_tblAttribute.get(ATTR_CODE);
return (attr == null ? (CodeAttribute) addAttribute(ATTR_CODE) : attr);
}
/**
* Determine if the method is deprecated.
*
* @return true if deprecated, false otherwise
*/
public boolean isDeprecated()
{
return m_tblAttribute.contains(ATTR_DEPRECATED);
}
/**
* Toggle if the method is deprecated.
*
* @param fDeprecated pass true to deprecate, false otherwise
*/
public void setDeprecated(boolean fDeprecated)
{
if (fDeprecated)
{
addAttribute(ATTR_DEPRECATED);
}
else
{
removeAttribute(ATTR_DEPRECATED);
}
}
/**
* Determine if the method is synthetic.
*
* @return true if synthetic, false otherwise
*/
public boolean isSynthetic()
{
return m_tblAttribute.contains(ATTR_SYNTHETIC) ||
m_flags.isSynthetic();
}
/**
* Toggle if the method is synthetic.
*
* @param fSynthetic pass true to set synthetic, false otherwise
*/
public void setSynthetic(boolean fSynthetic)
{
if (fSynthetic)
{
addAttribute(ATTR_SYNTHETIC);
}
else
{
removeAttribute(ATTR_SYNTHETIC);
}
}
/**
* Add an exception.
*
* @param sClz the class name of the exception
*/
public void addException(String sClz)
{
ExceptionsAttribute attr = (ExceptionsAttribute) getAttribute(ATTR_EXCEPTIONS);
if (attr == null)
{
attr = (ExceptionsAttribute) addAttribute(ATTR_EXCEPTIONS);
}
attr.addException(sClz);
}
/**
* Remove an exception.
*
* @param sClz the class name of the exception
*/
public void removeException(String sClz)
{
ExceptionsAttribute attr = (ExceptionsAttribute) m_tblAttribute.get(ATTR_EXCEPTIONS);
if (attr != null)
{
attr.removeException(sClz);
}
}
/**
* Access the set of exceptions.
*
* @return an enumeration of exception class names
*/
public Enumeration getExceptions()
{
ExceptionsAttribute attr = (ExceptionsAttribute) getAttribute(ATTR_EXCEPTIONS);
return attr == null ? NullImplementation.getEnumeration() : attr.getExceptions();
}
// ----- helpers --------------------------------------------------------
/**
* The class name if this method is from disassembly.
*
* @return the class name as it was found in the constant pool
*/
protected String getClassName()
{
return m_sClass;
}
/**
* Ensure a {@link MethodParametersAttribute} exists as method_info
* attribute.
*
* @param cParams the number of parameters defined by this method's signature
*
* @return a MethodParametersAttribute linked to this Method
*/
protected MethodParametersAttribute ensureMethodParameters(int cParams)
{
MethodParametersAttribute attrParams = (MethodParametersAttribute)
getAttribute(ATTR_METHODPARAMS);
if (attrParams == null)
{
attrParams = (MethodParametersAttribute) addAttribute(ATTR_METHODPARAMS);
attrParams.setParameterCount(cParams);
}
return attrParams;
}
// ----- constants ------------------------------------------------------
/**
* The name of this class.
*/
private static final String CLASS = "Method";
/**
* Access flags applicable to a method.
*/
public static final int ACC_METHOD = AccessFlags.ACC_PUBLIC |
AccessFlags.ACC_PRIVATE |
AccessFlags.ACC_PROTECTED |
AccessFlags.ACC_STATIC |
AccessFlags.ACC_FINAL |
AccessFlags.ACC_SYNCHRONIZED |
AccessFlags.ACC_BRIDGE |
AccessFlags.ACC_VARARGS |
AccessFlags.ACC_NATIVE |
AccessFlags.ACC_ABSTRACT |
AccessFlags.ACC_STRICT |
AccessFlags.ACC_SYNTHETIC;
// ----- data members ---------------------------------------------------
/**
* Whether this method is defined against an interface or a class.
*/
private final boolean f_fInterface;
/**
* The name of the class if this method is the result of disassembly.
*/
private String m_sClass;
/**
* The name of the method.
*/
private UtfConstant m_utfName;
/**
* The signature of the method.
*/
private UtfConstant m_utfSig;
/**
* The AccessFlags structure contained in the method.
*/
private AccessFlags m_flags = new AccessFlags()
{
@Override
protected void preassemble(ConstantPool pool)
{
if (f_fInterface)
{
if (isMaskSet(ACC_PROTECTED | ACC_FINAL | ACC_SYNCHRONIZED | ACC_NATIVE))
{
throw new IllegalStateException("Interface method " + this + " can not be "
+ "protected, final, synchronized, or native");
}
if (pool.getClassFile().getMajorVersion() < 52)
{
setPublic();
setAbstract(true);
}
else if (!isPublic() && !isPrivate())
{
throw new IllegalStateException("Interface method " + this + " must be "
+ "either public or private");
}
}
if (isAbstract() && isMaskSet(ACC_PRIVATE | ACC_STATIC | ACC_FINAL |
ACC_SYNCHRONIZED | ACC_NATIVE | ACC_STRICT))
{
throw new IllegalStateException("Abstract Method " + this + " can not be "
+ "private, static, final, synchronized, native, or strict");
}
super.preassemble(pool);
}
};
/**
* The Attribute structures contained in the method.
*/
private StringTable m_tblAttribute = new StringTable();
/**
* Tracks changes to the method.
*/
private boolean m_fModified;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy