2

I found the following construction in legacy java bytecode while trying to troubleshoot server application startup. My IDE decompiled some third party libraries and I'm curious how this can be valid - never saw before keywords can be used as field names in bytecode.

Bytecode version is 48.0 (Java 1.4).

public final class f implements UserContext{

private final String try;
private final UserInfo do;

// a lot of code here 

public UserInfo getUserInfo(){
    return this.do;
}

public String getViewName(){
    return this.try;
}

}

Seems like the library was compiled using some obfuscation features, but how can it be on JVM level? Is it permissible without special flags on JVM startup?

UPDATE : the correct getter name for UserInfo field is getUserInfo -- sorry for confusing everyone with ambiguous naming for methods with different return values, it's a copy-paste issue as code is located on a remote machine w/o direct access to the site.

  • `return this.do` is the same as `return do`. It isn't a name of a field, it simply means, return do from the yourself. When programming java adding it is optional, the compiler will add it, however it might remain when decompiling it afterwards. – M. Deinum Sep 10 '19 at 09:14
  • 4
    The real question should probably be "How can this code use reserved keywords as field names?" – Roger Gustavsson Sep 10 '19 at 09:15
  • 3
    What you are showing is not bytecode. It's decompiled Java code. That is, the problem could be in the decompiler, not in the java code itself. – RealSkeptic Sep 10 '19 at 09:18
  • @M.Deinum in which regard is returning something “from the yourself” not referring to a field by name? – Holger Sep 10 '19 at 10:55

4 Answers4

5

The Java Virtual Machine Specification (which is responsible for defining what the bytecode looks like) puts no constraints related to keywords on the names of things.

Those constraints only exist on the Java Language level. The bytecode you used does not decompile into valid Java, because it uses names that are not valid in the Java language, but that are valid to the JVM.

A similar logic applies to the two getViewName methods that differ only in return type: This is allowed (and works perfectly fine) in bytecode by the JVM spec, but the Java Language specification forbids it.

The most common reason for bytecode like this is Java code that was compiled to bytecode and then obfuscated.

Another possible reason is that the code was not originally produced by compiling Java code, but another language that targets the JVM. This is rather unlikely in this case, since no one would name a variable do when it's supposed to hold the view name.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • Thanks, Joachim. It's definitely ```Java 1.4``` and code is written in ~2003-2004 (I'm not sure if other languages like [Groovy](https://en.wikipedia.org/wiki/Apache_Groovy) or [Scala](https://en.wikipedia.org/wiki/Scala_(programming_language)) were production-ready [at that time](https://en.wikipedia.org/wiki/Java_version_history) – The Rabbit of No Luck Sep 10 '19 at 09:57
  • 2
    …and the author of the obfuscation tool lacked the creativity to come up with even worse. Note that on the bytecode level, even fields can have the same name if they are still distinguishable by their type. Also, the names are not even required to form words, a line break would be a valid name too and the field name could be `a+1` (which is especially funny when also having a variable `a` and `a+2`, etc. See also [this answer](https://stackoverflow.com/a/30502309/2711488). By the way, since Java 5, the compiler may generate bridge methods which only differ in the return types. – Holger Sep 10 '19 at 11:05
2

I'd almost think that the code were obfuscated, but then you would see it in method names as well. Sometimes obfuscators do things that aren't allowed in the language, so when you decompile them you can't recompile the source. It's only the Java syntax that doesn't allow do or try as variable names, the JVM (and other languages that run on the JVM) doen't care about it.

Either this was deliberate obfuscation or they were not compiled from Java classes.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • 1
    It's quite common to obfuscate only non-public parts of the code (for example when other un-obfuscated code is required to interact with yours). I'm pretty sure this is the result of bytecode obfuscation. – Joachim Sauer Sep 10 '19 at 09:30
  • @JoachimSauer it sure looks like it. Of course the `getViewName()` methods are invalid as well, since they have the same signature. – Kayaman Sep 10 '19 at 09:45
  • Guys, sorry: if course, it was a mistake in method names - due to copy-paste. The only question is regarding keywords. – The Rabbit of No Luck Sep 10 '19 at 10:21
1

This could be some form of obfuscation.

The string try could perhaps be trу. They are actually different. Cut & paste the first one and it will be treated as the reserved keyword try. Cut & paste the second one and it will be a valid field name. The y in the second case is not a normal y. It's a different unicode character.

Roger Gustavsson
  • 1,689
  • 10
  • 20
0

You can't use keywords as variable names, see chapter 3.9 in the Java Language Specification.

The decompiler gave you bad/buggy code.

nos
  • 223,662
  • 58
  • 417
  • 506