Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/MemberDefinition.java
38918 views
/*1* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.java;2627import sun.tools.tree.Node;28import sun.tools.tree.Vset;29import sun.tools.tree.Expression;30import sun.tools.tree.Statement;31import sun.tools.tree.Context;32import sun.tools.asm.Assembler;33import java.io.PrintStream;34import java.util.Vector;35import java.util.Map;36import java.util.HashMap;3738/**39* This class defines a member of a Java class:40* a variable, a method, or an inner class.41*42* WARNING: The contents of this source file are not part of any43* supported API. Code that depends on them does so at its own risk:44* they are subject to change or removal without notice.45*/46public47class MemberDefinition implements Constants {48protected long where;49protected int modifiers;50protected Type type;51protected String documentation;52protected IdentifierToken expIds[];53protected ClassDeclaration exp[];54protected Node value;55protected ClassDefinition clazz;56protected Identifier name;57protected ClassDefinition innerClass;58protected MemberDefinition nextMember;59protected MemberDefinition nextMatch;60protected MemberDefinition accessPeer;61protected boolean superAccessMethod;6263/**64* Constructor65*/66public MemberDefinition(long where, ClassDefinition clazz, int modifiers,67Type type, Identifier name,68IdentifierToken expIds[], Node value) {69if (expIds == null) {70expIds = new IdentifierToken[0];71}72this.where = where;73this.clazz = clazz;74this.modifiers = modifiers;75this.type = type;76this.name = name;77this.expIds = expIds;78this.value = value;79}8081/**82* Constructor for an inner class.83* Inner classes are represented as fields right along with84* variables and methods for simplicity of data structure,85* and to reflect properly the textual declaration order.86* <p>87* This constructor calls the generic constructor for this88* class, extracting all necessary values from the innerClass.89*/90public MemberDefinition(ClassDefinition innerClass) {91this(innerClass.getWhere(),92innerClass.getOuterClass(),93innerClass.getModifiers(),94innerClass.getType(),95innerClass.getName().getFlatName().getName(),96null, null);97this.innerClass = innerClass;98}99100/**101* A cache of previously created proxy members. Used to ensure102* uniqueness of proxy objects. See the makeProxyMember method103* defined below.104*/105static private Map proxyCache;106107/**108* Create a member which is externally the same as `field' but109* is defined in class `classDef'. This is used by code110* in sun.tools.tree.(MethodExpression,FieldExpression) as111* part of the fix for bug 4135692.112*113* Proxy members should not be added, ala addMember(), to classes.114* They are merely "stand-ins" to produce modified MethodRef115* constant pool entries during code generation.116*117* We keep a cache of previously created proxy members not to118* save time or space, but to ensure uniqueness of the proxy119* member for any (field,classDef) pair. If these are not made120* unique then we can end up generating duplicate MethodRef121* constant pool entries during code generation.122*/123public static MemberDefinition makeProxyMember(MemberDefinition field,124ClassDefinition classDef,125Environment env) {126127if (proxyCache == null) {128proxyCache = new HashMap();129}130131String key = field.toString() + "@" + classDef.toString();132// System.out.println("Key is : " + key);133MemberDefinition proxy = (MemberDefinition)proxyCache.get(key);134135if (proxy != null)136return proxy;137138proxy = new MemberDefinition(field.getWhere(), classDef,139field.getModifiers(), field.getType(),140field.getName(), field.getExceptionIds(),141null);142proxy.exp = field.getExceptions(env);143proxyCache.put(key, proxy);144145return proxy;146}147148/**149* Get the position in the input150*/151public final long getWhere() {152return where;153}154155/**156* Get the class declaration157*/158public final ClassDeclaration getClassDeclaration() {159return clazz.getClassDeclaration();160}161162/**163* A stub. Subclasses can do more checking.164*/165public void resolveTypeStructure(Environment env) {166}167168/**169* Get the class declaration in which the field is actually defined170*/171public ClassDeclaration getDefiningClassDeclaration() {172return getClassDeclaration();173}174175/**176* Get the class definition177*/178public final ClassDefinition getClassDefinition() {179return clazz;180}181182/**183* Get the field's top-level enclosing class184*/185public final ClassDefinition getTopClass() {186return clazz.getTopClass();187}188189/**190* Get the field's modifiers191*/192public final int getModifiers() {193return modifiers;194}195public final void subModifiers(int mod) {196modifiers &= ~mod;197}198public final void addModifiers(int mod) {199modifiers |= mod;200}201202/**203* Get the field's type204*/205public final Type getType() {206return type;207}208209/**210* Get the field's name211*/212public final Identifier getName() {213return name;214}215216/**217* Get arguments (a vector of LocalMember)218*/219public Vector getArguments() {220return isMethod() ? new Vector() : null;221}222223/**224* Get the exceptions that are thrown by this method.225*/226public ClassDeclaration[] getExceptions(Environment env) {227if (expIds != null && exp == null) {228if (expIds.length == 0)229exp = new ClassDeclaration[0];230else231// we should have translated this already!232throw new CompilerError("getExceptions "+this);233}234return exp;235}236237public final IdentifierToken[] getExceptionIds() {238return expIds;239}240241/**242* Get an inner class.243*/244public ClassDefinition getInnerClass() {245return innerClass;246}247248/**249* Is this a synthetic field which holds a copy of,250* or reference to, a local variable or enclosing instance?251*/252public boolean isUplevelValue() {253if (!isSynthetic() || !isVariable() || isStatic()) {254return false;255}256String name = this.name.toString();257return name.startsWith(prefixVal)258|| name.startsWith(prefixLoc)259|| name.startsWith(prefixThis);260}261262public boolean isAccessMethod() {263// This no longer works, because access methods264// for constructors do not use the standard naming265// scheme.266// return isSynthetic() && isMethod()267// && name.toString().startsWith(prefixAccess);268// Assume that a method is an access method if it has269// an access peer. NOTE: An access method will not be270// recognized as such until 'setAccessMethodTarget' has271// been called on it.272return isSynthetic() && isMethod() && (accessPeer != null);273}274275/**276* Is this a synthetic method which provides access to a277* visible private member?278*/279public MemberDefinition getAccessMethodTarget() {280if (isAccessMethod()) {281for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) {282// perhaps skip over another access for the same field283if (!f.isAccessMethod()) {284return f;285}286}287}288return null;289}290291292public void setAccessMethodTarget(MemberDefinition target) {293if (getAccessMethodTarget() != target) {294/*-------------------*295if (!isAccessMethod() || accessPeer != null ||296target.accessPeer != null) {297throw new CompilerError("accessPeer");298}299*-------------------*/300if (accessPeer != null || target.accessPeer != null) {301throw new CompilerError("accessPeer");302}303accessPeer = target;304}305}306307/**308* If this method is a getter for a private field, return the setter.309*/310public MemberDefinition getAccessUpdateMember() {311if (isAccessMethod()) {312for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) {313if (f.isAccessMethod()) {314return f;315}316}317}318return null;319}320321public void setAccessUpdateMember(MemberDefinition updater) {322if (getAccessUpdateMember() != updater) {323if (!isAccessMethod() ||324updater.getAccessMethodTarget() != getAccessMethodTarget()) {325throw new CompilerError("accessPeer");326}327updater.accessPeer = accessPeer;328accessPeer = updater;329}330}331332/**333* Is this an access method for a field selection or method call334* of the form '...super.foo' or '...super.foo()'?335*/336public final boolean isSuperAccessMethod() {337return superAccessMethod;338}339340/**341* Mark this member as an access method for a field selection342* or method call via the 'super' keyword.343*/344public final void setIsSuperAccessMethod(boolean b) {345superAccessMethod = b;346}347348/**349* Tell if this is a final variable without an initializer.350* Such variables are subject to definite single assignment.351*/352public final boolean isBlankFinal() {353return isFinal() && !isSynthetic() && getValue() == null;354}355356public boolean isNeverNull() {357if (isUplevelValue()) {358// loc$x and this$C are never null359return !name.toString().startsWith(prefixVal);360}361return false;362}363364/**365* Get the field's final value (may return null)366*/367public Node getValue(Environment env) throws ClassNotFound {368return value;369}370public final Node getValue() {371return value;372}373public final void setValue(Node value) {374this.value = value;375}376public Object getInitialValue() {377return null;378}379380/**381* Get the next field or the next match382*/383public final MemberDefinition getNextMember() {384return nextMember;385}386public final MemberDefinition getNextMatch() {387return nextMatch;388}389390/**391* Get the field's documentation392*/393public String getDocumentation() {394return documentation;395}396397/**398* Request a check of the field definition.399*/400public void check(Environment env) throws ClassNotFound {401}402403/**404* Really check the field definition.405*/406public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound {407return vset;408}409410/**411* Generate code412*/413public void code(Environment env, Assembler asm) throws ClassNotFound {414throw new CompilerError("code");415}416public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {417throw new CompilerError("codeInit");418}419420/**421* Tells whether to report a deprecation error for this field.422*/423public boolean reportDeprecated(Environment env) {424return (isDeprecated() || clazz.reportDeprecated(env));425}426427/**428* Check if a field can reach another field (only considers429* forward references, not the access modifiers).430*/431public final boolean canReach(Environment env, MemberDefinition f) {432if (f.isLocal() || !f.isVariable() || !(isVariable() || isInitializer()))433return true;434if ((getClassDeclaration().equals(f.getClassDeclaration())) &&435(isStatic() == f.isStatic())) {436// They are located in the same class, and are either both437// static or both non-static. Check the initialization order.438while (((f = f.getNextMember()) != null) && (f != this));439return f != null;440}441return true;442}443444//-----------------------------------------------------------------445// The code in this section is intended to test certain kinds of446// compatibility between methods. There are two kinds of compatibility447// that the compiler may need to test. The first is whether one448// method can legally override another. The second is whether two449// method definitions can legally coexist. We use the word `meet'450// to mean the intersection of two legally coexisting methods.451// For more information on these kinds of compatibility, see the452// comments/code for checkOverride() and checkMeet() below.453454/**455* Constants used by getAccessLevel() to represent the access456* modifiers as numbers.457*/458static final int PUBLIC_ACCESS = 1;459static final int PROTECTED_ACCESS = 2;460static final int PACKAGE_ACCESS = 3;461static final int PRIVATE_ACCESS = 4;462463/**464* Return the access modifier of this member as a number. The idea465* is that this number may be used to check properties like "the466* access modifier of x is more restrictive than the access467* modifier of y" with a simple inequality test:468* "x.getAccessLevel() > y.getAccessLevel.469*470* This is an internal utility method.471*/472private int getAccessLevel() {473// Could just compute this once instead of recomputing.474// Check to see if this is worth it.475if (isPublic()) {476return PUBLIC_ACCESS;477} else if (isProtected()) {478return PROTECTED_ACCESS;479} else if (isPackagePrivate()) {480return PACKAGE_ACCESS;481} else if (isPrivate()) {482return PRIVATE_ACCESS;483} else {484throw new CompilerError("getAccessLevel()");485}486}487488/**489* Munge our error message to report whether the override conflict490* came from an inherited method or a declared method.491*/492private void reportError(Environment env, String errorString,493ClassDeclaration clazz,494MemberDefinition method) {495496if (clazz == null) {497// For example:498// "Instance method BLAH inherited from CLASSBLAH1 cannot be499// overridden by the static method declared in CLASSBLAH2."500env.error(getWhere(), errorString,501this, getClassDeclaration(),502method.getClassDeclaration());503} else {504// For example:505// "In CLASSBLAH1, instance method BLAH inherited from CLASSBLAH2506// cannot be overridden by the static method inherited from507// CLASSBLAH3."508env.error(clazz.getClassDefinition().getWhere(),509//"inherit." + errorString,510errorString,511//clazz,512this, getClassDeclaration(),513method.getClassDeclaration());514}515}516517/**518* Convenience method to see if two methods return the same type519*/520public boolean sameReturnType(MemberDefinition method) {521// Make sure both are methods.522if (!isMethod() || !method.isMethod()) {523throw new CompilerError("sameReturnType: not method");524}525526Type myReturnType = getType().getReturnType();527Type yourReturnType = method.getType().getReturnType();528529return (myReturnType == yourReturnType);530}531532/**533* Check to see if `this' can override/hide `method'. Caller is534* responsible for verifying that `method' has the same signature535* as `this'. Caller is also responsible for verifying that536* `method' is visible to the class where this override is occurring.537* This method is called for the case when class B extends A and both538* A and B define some method.539* <pre>540* A - void foo() throws e1541* |542* |543* B - void foo() throws e2544* </pre>545*/546public boolean checkOverride(Environment env, MemberDefinition method) {547return checkOverride(env, method, null);548}549550/**551* Checks whether `this' can override `method'. It `clazz' is552* null, it reports the errors in the class where `this' is553* declared. If `clazz' is not null, it reports the error in `clazz'.554*/555private boolean checkOverride(Environment env,556MemberDefinition method,557ClassDeclaration clazz) {558// This section of code is largely based on section 8.4.6.3559// of the JLS.560561boolean success = true;562563// Sanity564if (!isMethod()) {565throw new CompilerError("checkOverride(), expected method");566}567568// Suppress checks for synthetic methods, as the compiler presumably569// knows what it is doing, e.g., access methods.570if (isSynthetic()) {571// Sanity check: We generally do not intend for one synthetic572// method to override another, though hiding of static members573// is expected. This check may need to be changed if new uses574// of synthetic methods are devised.575//576// Query: this code was copied from elsewhere. What577// exactly is the role of the !isStatic() in the test?578if (method.isFinal() ||579(!method.isConstructor() &&580!method.isStatic() && !isStatic())) {581////////////////////////////////////////////////////////////582// NMG 2003-01-28 removed the following test because it is583// invalidated by bridge methods inserted by the "generic"584// (1.5) Java compiler. In 1.5, this code is used,585// indirectly, by rmic586////////////////////////////////////////////////////////////587// throw new CompilerError("checkOverride() synthetic");588////////////////////////////////////////////////////////////589}590591// We trust the compiler. (Ha!) We're done checking.592return true;593}594595// Our caller should have verified that the method had the596// same signature.597if (getName() != method.getName() ||598!getType().equalArguments(method.getType())) {599600throw new CompilerError("checkOverride(), signature mismatch");601}602603// It is forbidden to `override' a static method with an instance604// method.605if (method.isStatic() && !isStatic()) {606reportError(env, "override.static.with.instance", clazz, method);607success = false;608}609610// It is forbidden to `hide' an instance method with a static611// method.612if (!method.isStatic() && isStatic()) {613reportError(env, "hide.instance.with.static", clazz, method);614success = false;615}616617// We cannot override a final method.618if (method.isFinal()) {619reportError(env, "override.final.method", clazz, method);620success = false;621}622623// Give a warning when we override a deprecated method with624// a non-deprecated one.625//626// We bend over backwards to suppress this warning if627// the `method' has not been already compiled or628// `this' has been already compiled.629if (method.reportDeprecated(env) && !isDeprecated()630&& this instanceof sun.tools.javac.SourceMember) {631reportError(env, "warn.override.is.deprecated",632clazz, method);633}634635// Visibility may not be more restrictive636if (getAccessLevel() > method.getAccessLevel()) {637reportError(env, "override.more.restrictive", clazz, method);638success = false;639}640641// Return type equality642if (!sameReturnType(method)) {643////////////////////////////////////////////////////////////644// PCJ 2003-07-30 removed the following error because it is645// invalidated by the covariant return type feature of the646// 1.5 compiler. The resulting check is now much looser647// than the actual 1.5 language spec, but that should be OK648// because this code is only still used by rmic. See 4892308.649////////////////////////////////////////////////////////////650// reportError(env, "override.different.return", clazz, method);651// success = false;652////////////////////////////////////////////////////////////653}654655// Exception agreeement656if (!exceptionsFit(env, method)) {657reportError(env, "override.incompatible.exceptions",658clazz, method);659success = false;660}661662return success;663}664665/**666* Check to see if two method definitions are compatible, that is667* do they have a `meet'. The meet of two methods is essentially668* and `intersection' of669* two methods. This method is called when some class C inherits670* declarations for some method foo from two parents (superclass,671* interfaces) but it does not, itself, have a declaration of foo.672* Caller is responsible for making sure that both methods are673* indeed visible in clazz.674* <pre>675* A - void foo() throws e1676* \677* \ B void foo() throws e2678* \ /679* \ /680* C681* </pre>682*/683public boolean checkMeet(Environment env,684MemberDefinition method,685ClassDeclaration clazz) {686// This section of code is largely based on Section 8.4.6687// and 9.4.1 of the JLS.688689// Sanity690if (!isMethod()) {691throw new CompilerError("checkMeet(), expected method");692}693694// Check for both non-abstract.695if (!isAbstract() && !method.isAbstract()) {696throw new CompilerError("checkMeet(), no abstract method");697}698699// If either method is non-abstract, then we need to check that700// the abstract method can be properly overridden. We call701// the checkOverride method to check this and generate any errors.702// This test must follow the previous test.703else if (!isAbstract()) {704return checkOverride(env, method, clazz);705} else if (!method.isAbstract()) {706return method.checkOverride(env, this, clazz);707}708709// Both methods are abstract.710711// Our caller should have verified that the method has the712// same signature.713if (getName() != method.getName() ||714!getType().equalArguments(method.getType())) {715716throw new CompilerError("checkMeet(), signature mismatch");717}718719// Check for return type equality720if (!sameReturnType(method)) {721// More args?722env.error(clazz.getClassDefinition().getWhere(),723"meet.different.return",724this, this.getClassDeclaration(),725method.getClassDeclaration());726return false;727}728729// We don't have to check visibility -- there always730// potentially exists a meet. Similarly with exceptions.731732// There does exist a meet.733return true;734}735736/**737* This method is meant to be used to determine if one of two inherited738* methods could override the other. Unlike checkOverride(), failure739* is not an error. This method is only meant to be called after740* checkMeet() has succeeded on the two methods.741*742* If you call couldOverride() without doing a checkMeet() first, then743* you are on your own.744*/745public boolean couldOverride(Environment env,746MemberDefinition method) {747748// Sanity749if (!isMethod()) {750throw new CompilerError("coulcOverride(), expected method");751}752753// couldOverride() is only called with `this' and `method' both754// being inherited methods. Neither of them is defined in the755// class which we are currently working on. Even though an756// abstract method defined *in* a class can override a non-abstract757// method defined in a superclass, an abstract method inherited758// from an interface *never* can override a non-abstract method.759// This comment may sound odd, but that's the way inheritance is.760// The following check makes sure we aren't trying to override761// an inherited non-abstract definition with an abstract definition762// from an interface.763if (!method.isAbstract()) {764return false;765}766767// Visibility should be less restrictive768if (getAccessLevel() > method.getAccessLevel()) {769return false;770}771772// Exceptions773if (!exceptionsFit(env, method)) {774return false;775}776777// Potentially some deprecation warnings could be given here778// when we merge two abstract methods, one of which is deprecated.779// This is not currently reported.780781return true;782}783784/**785* Check to see if the exceptions of `this' fit within the786* exceptions of `method'.787*/788private boolean exceptionsFit(Environment env,789MemberDefinition method) {790ClassDeclaration e1[] = getExceptions(env); // my exceptions791ClassDeclaration e2[] = method.getExceptions(env); // parent's792793// This code is taken nearly verbatim from the old implementation794// of checkOverride() in SourceClass.795outer:796for (int i = 0 ; i < e1.length ; i++) {797try {798ClassDefinition c1 = e1[i].getClassDefinition(env);799for (int j = 0 ; j < e2.length ; j++) {800if (c1.subClassOf(env, e2[j])) {801continue outer;802}803}804if (c1.subClassOf(env,805env.getClassDeclaration(idJavaLangError)))806continue outer;807if (c1.subClassOf(env,808env.getClassDeclaration(idJavaLangRuntimeException)))809continue outer;810811// the throws was neither something declared by a parent,812// nor one of the ignorables.813return false;814815} catch (ClassNotFound ee) {816// We were unable to find one of the exceptions.817env.error(getWhere(), "class.not.found",818ee.name, method.getClassDeclaration());819}820}821822// All of the exceptions `fit'.823return true;824}825826//-----------------------------------------------------------------827828/**829* Checks830*/831public final boolean isPublic() {832return (modifiers & M_PUBLIC) != 0;833}834public final boolean isPrivate() {835return (modifiers & M_PRIVATE) != 0;836}837public final boolean isProtected() {838return (modifiers & M_PROTECTED) != 0;839}840public final boolean isPackagePrivate() {841return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;842}843public final boolean isFinal() {844return (modifiers & M_FINAL) != 0;845}846public final boolean isStatic() {847return (modifiers & M_STATIC) != 0;848}849public final boolean isSynchronized() {850return (modifiers & M_SYNCHRONIZED) != 0;851}852public final boolean isAbstract() {853return (modifiers & M_ABSTRACT) != 0;854}855public final boolean isNative() {856return (modifiers & M_NATIVE) != 0;857}858public final boolean isVolatile() {859return (modifiers & M_VOLATILE) != 0;860}861public final boolean isTransient() {862return (modifiers & M_TRANSIENT) != 0;863}864public final boolean isMethod() {865return type.isType(TC_METHOD);866}867public final boolean isVariable() {868return !type.isType(TC_METHOD) && innerClass == null;869}870public final boolean isSynthetic() {871return (modifiers & M_SYNTHETIC) != 0;872}873public final boolean isDeprecated() {874return (modifiers & M_DEPRECATED) != 0;875}876public final boolean isStrict() {877return (modifiers & M_STRICTFP) != 0;878}879public final boolean isInnerClass() {880return innerClass != null;881}882public final boolean isInitializer() {883return getName().equals(idClassInit);884}885public final boolean isConstructor() {886return getName().equals(idInit);887}888public boolean isLocal() {889return false;890}891public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {892return (isStatic() || isPrivate() || isFinal() || isConstructor() || fromFinal) &&893!(isSynchronized() || isNative());894}895896/**897* Check if constant: Will it inline away to a constant?898*/899public boolean isConstant() {900if (isFinal() && isVariable() && value != null) {901try {902// If an infinite regress requeries this name,903// deny that it is a constant.904modifiers &= ~M_FINAL;905return ((Expression)value).isConstant();906} finally {907modifiers |= M_FINAL;908}909}910return false;911}912913/**914* toString915*/916public String toString() {917Identifier name = getClassDefinition().getName();918if (isInitializer()) {919return isStatic() ? "static {}" : "instance {}";920} else if (isConstructor()) {921StringBuffer buf = new StringBuffer();922buf.append(name);923buf.append('(');924Type argTypes[] = getType().getArgumentTypes();925for (int i = 0 ; i < argTypes.length ; i++) {926if (i > 0) {927buf.append(',');928}929buf.append(argTypes[i].toString());930}931buf.append(')');932return buf.toString();933} else if (isInnerClass()) {934return getInnerClass().toString();935}936return type.typeString(getName().toString());937}938939/**940* Print for debugging941*/942public void print(PrintStream out) {943if (isPublic()) {944out.print("public ");945}946if (isPrivate()) {947out.print("private ");948}949if (isProtected()) {950out.print("protected ");951}952if (isFinal()) {953out.print("final ");954}955if (isStatic()) {956out.print("static ");957}958if (isSynchronized()) {959out.print("synchronized ");960}961if (isAbstract()) {962out.print("abstract ");963}964if (isNative()) {965out.print("native ");966}967if (isVolatile()) {968out.print("volatile ");969}970if (isTransient()) {971out.print("transient ");972}973out.println(toString() + ";");974}975976public void cleanup(Environment env) {977documentation = null;978if (isMethod() && value != null) {979int cost = 0;980if (isPrivate() || isInitializer()) {981value = Statement.empty;982} else if ((cost =983((Statement)value)984.costInline(Statement.MAXINLINECOST, null, null))985>= Statement.MAXINLINECOST) {986// will never be inlined987value = Statement.empty;988} else {989try {990if (!isInlineable(null, true)) {991value = Statement.empty;992}993}994catch (ClassNotFound ee) { }995}996if (value != Statement.empty && env.dump()) {997env.output("[after cleanup of " + getName() + ", " +998cost + " expression cost units remain]");999}1000} else if (isVariable()) {1001if (isPrivate() || !isFinal() || type.isType(TC_ARRAY)) {1002value = null;1003}1004}1005}1006}100710081009