Class Oaktree
- Author:
- Geolykt
-
Field Summary
FieldsModifier and TypeFieldDescriptionA hardcoded set of implementations of theCollectioninterface that apply for generics checking later on.A hardcoded set of implementations of theIterableinterface that apply for generics checking later on.static final int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionAnalyses the likely generic type of the return value of methods.voidApplies the inner class nodes to any encountered classes.voidRemoves the final access modifier from non-obfuscated anonymous classes.voidfixComparators(boolean resolveTRArtifact) Add the signature of obvious bridge methods (i.intResolve useless <unknown> mentions when quiltflower decompiles enhanced for loops that loop on arrays by adding their respective LVT entries via guessing.voidGuesses the inner classes from class nodesvoidMethod that tries to put the Local Variable Table (LVT) in a acceptable state by synchronising parameter declarations with lvt declarations.intMethod that tries to restore the SwitchMaps to how they should be.List<org.objectweb.asm.tree.ClassNode>getProposedLocalClassNames(String localClassNamePrefix, BiPredicate<String, String> condition, boolean applyInnerClassNodes) Guesses which classes are a local class within a certain class.static final @Nullable StringgetReturnedClass(String methodDesc) Obtains the internal name of the class that is returned by a given method descriptor.Guesses the should-be inner classes of classes based on the usages of the class.intGuesses anonymous inner classes by checking whether they have a synthetic field and if they do whether they are referenced only by a single "parent" class.intGuesses the generic signatures of fields based on their usage.Guesses which classes are local classes within another class.voidvoidInfers the generics of constructors based on the calls to the constructor.intInfers the generic signatures of methods based on the contents of the method.voidInvalidate internalClassNodenamecaches.voidlambdaStreamGenericSignatureGuessing(Map<FieldReference, ClassWrapper> fields, Map<MethodReference, ClassWrapper> methods) static voidvoidwrite(@NotNull OutputStream out, @NotNull Path resources) Write all class nodes and copy over all resources from a given jar.voidwrite(OutputStream out)
-
Field Details
-
COLLECTIONS
A hardcoded set of implementations of theCollectioninterface that apply for generics checking later on. -
ITERABLES
A hardcoded set of implementations of theIterableinterface that apply for generics checking later on. -
JAVA_KEYWORDS
-
VISIBILITY_MODIFIERS
public static final int VISIBILITY_MODIFIERS- See Also:
-
-
Constructor Details
-
Oaktree
public Oaktree() -
Oaktree
-
-
Method Details
-
getReturnedClass
@Nullable @Contract(pure=true) public static final @Nullable String getReturnedClass(String methodDesc) Obtains the internal name of the class that is returned by a given method descriptor. If not an object (or array) is returned as according to the method descriptor, null is returned by this method. For arrays, the leading "[" are removed - so it is not possible to differ between array and "normal" object.This method was created in anticipation of L-World.
- Parameters:
methodDesc- The method descriptor- Returns:
- The internal name of the object or array returned by the method.
-
main
-
applyInnerclasses
public void applyInnerclasses()Applies the inner class nodes to any encountered classes. -
definalizeAnonymousClasses
public void definalizeAnonymousClasses()Removes the final access modifier from non-obfuscated anonymous classes. The reason this is done is because for recompiled galimulator (using Java 17 to compile and target 1.8), the access modifiers differ in this instance. Why exactly this is the case is unknown to me. -
fixComparators
public void fixComparators(boolean resolveTRArtifact) Add the signature of obvious bridge methods (i. e. comparators).- Parameters:
resolveTRArtifact- Whether to resolve an artifact left over by tiny remapper.
-
fixForeachOnArray
public int fixForeachOnArray()Resolve useless <unknown> mentions when quiltflower decompiles enhanced for loops that loop on arrays by adding their respective LVT entries via guessing. However since this requires the knowledge of the array type, this may not always be successful.
As this modifies the LVT entries, it should be called AFTERfixParameterLVT().- Returns:
- The amount of added LVTs
-
fixInnerClasses
public void fixInnerClasses()Guesses the inner classes from class nodes -
fixParameterLVT
public void fixParameterLVT()Method that tries to put the Local Variable Table (LVT) in a acceptable state by synchronising parameter declarations with lvt declarations. Does not do anything to the LVT if the LVT is declared but empty, which is a sign of the usage of obfuscation tools. It is intended to be used in combination with decompilers such as quiltflower but might not be useful for less naive decompilers such as procyon, which do not decompile into incoherent java code if the LVT is damaged. -
fixSwitchMaps
public int fixSwitchMaps()Method that tries to restore the SwitchMaps to how they should be. This includes marking the SwitchMap classes as anonymous classes, so it is likely that they cannot be referenced afterwards.It may prove useful to call methods such as
guessAnonymousInnerClasses()orguessLocalClasses()BEFORE calling this method, as it needs to find the outermost class of all classes. However if a class is not marked as an inner class of another class, then conflicts may occur as the SwitchMa would be an inner class of both classes. This state is nonsensical and hence warnings will be printed if it is encountered.- Returns:
- The amount of classes who were identified as switch maps.
-
getClassNodesDirectly
-
guessAnonymousClasses
Guesses the should-be inner classes of classes based on the usages of the class. This only guesses anonymous classes based on the code, but not based on the name. It also does not require the synthetic fields for the anonymous classes, so it may do mismatches from time to time.It will not overwrite already existing relations and will not perform any changes to the class nodes. Inner class nodes must therefore be applied manually. It is advisable to run
applyInnerclasses()afterwards.- Returns:
- The returned map will have the outer class as the key and the outer method as the desc.
-
analyseLikelyMethodReturnCollectionGenerics
Analyses the likely generic type of the return value of methods. The return value may only be an instance ofCollectionor an implementation of it (as defined throughClassWrapperPool.isImplementingInterface(ClassWrapper, String)).To reduce the imprecision of the used algorithm following filters are put in place:
- The method must be static
- The method must not already have a signature
- The method must not have arguments
StackWalkerand theClassWrapperPool, which means using this method may not always be beneficial.This method does not modify the signatures of methods directly. This operation would need to be done by an external method.
- Returns:
- A map that stores the location of the method as the key and the signature type as the value.
-
getProposedLocalClassNames
public Map<String,String> getProposedLocalClassNames(String localClassNamePrefix, BiPredicate<String, String> condition, boolean applyInnerClassNodes) Guesses which classes are a local class within a certain class. Other than anonymous classes, local classes can be references within the entire block. This method only supports guessing local classes within classes (may they be nested or not), however can also lead to it marking anonymous classes as local classes.The names of the local classes are inferred from outer class, the given prefix and their name compared to other local classes.
This method does not check for collision
This method will internally allow for large amounts of nesting - at performance cost, however should a recursive nest be assumed, the nest (and all nests depending on the nest) will be silently discarded.
- Parameters:
localClassNamePrefix- The prefix to use for naming local classescondition- A predicate that is called for each proposed mapping. First argument is the outer class, second argument the inner class. Should the predicate yield false, the relation is discarded.applyInnerClassNodes- Whether to applyInnerClassNodeto the inner AND outer class nodes. Making it false may requirefixInnerClasses()to be applied.- Returns:
- A map storing proposed renames of the inner classes.
-
guessAnonymousInnerClasses
public int guessAnonymousInnerClasses()Guesses anonymous inner classes by checking whether they have a synthetic field and if they do whether they are referenced only by a single "parent" class. Note: this method is VERY aggressive when it comes to adding inner classes, sometimes it adds inner classes on stuff where it wouldn't belong. This means that usage of this method should be done wisely. This method will do some damage even if it does no good.- Returns:
- The amount of guessed anonymous inner classes
-
guessFieldGenerics
public int guessFieldGenerics()Guesses the generic signatures of fields based on their usage. This might be inaccurate under some circumstances, however it tries to play it as safe as possible. The main algorithm in this method checks for generics via foreach iteration over the field and searches for the CHECKCAST to determine the signature. Note: this method should be invoked AFTERfixParameterLVT(), invoking this method before it would lead to LVT fixing not working properly- Returns:
- The amount of added field signatures
-
guessLocalClasses
Guesses which classes are local classes within another class. Local classes are non-static classes that are nested within another class or method.This method is rather aggressive and may recommend pairing that do not make sense. It is up to the API consumer to sort out nonsensical pairings from the ones that make sense.
Invoking this method does not have any effect in itself. The returned map should be used to create pairings.
- Returns:
- A map that has the inner classes as the key and their outer class as it's value.
-
index
-
inferConstructorGenerics
public void inferConstructorGenerics()Infers the generics of constructors based on the calls to the constructor. -
inferMethodGenerics
public int inferMethodGenerics()Infers the generic signatures of methods based on the contents of the method.- Returns:
- The amount of guessed signatures
-
invalidateNameCaches
public void invalidateNameCaches()Invalidate internalClassNodenamecaches. Should be invoked when for example class nodes are remapped, at which point internal caches are no longer valid. -
lambdaStreamGenericSignatureGuessing
public void lambdaStreamGenericSignatureGuessing(Map<FieldReference, ClassWrapper> fields, Map<MethodReference, ClassWrapper> methods) -
write
- Throws:
IOException
-
write
public void write(@NotNull @NotNull OutputStream out, @NotNull @NotNull Path resources) throws IOException Write all class nodes and copy over all resources from a given jar. This method throws an IOException if there is no file at the path "resources" or if it is not a zip (and by extension jar) file. If no resources need to be copied over,write(OutputStream)should be used instead.- Parameters:
out- The stream to write the nodes and resources to as a jarresources- The path to obtain resources from- Throws:
IOException- If something went wrong while writing to the stream or reading the resources jar.
-