java decompilation - java

When decompiling a specific jar using java decompiler (http://java.decompiler.free.fr/) I got some strange code I cannot identify what is. can someone help me? the code is something like:
Foo.access$004(Foo.this);
or this
Bar.access$006(Bar.this);
or else
Baz.access$102(Baz.this, true)
What are these methods access$004, access$006 and access$102?

Synthetic methods like this get created to support acessing private methods of inner classes. Since inner classes were not part of the initial jvm version, the access modifiers could not really handle this case. The solution was to create additional package-visible methods that delegate to the private implementation.
public class Example {
private static class Inner {
private void innerMethod() { ... }
}
public void test() {
Inner inner = ...
inner.innerMethod():
}
}
The compile would create a new method of the Inner class like this:
static void access$000(Inner inner) {
inner.innerMethod();
}
And replace the call in the test method like this:
Inner.access$000(inner);
The static access$000 is package visible and so accessible from the outer class, and being inside the same Inner class it can delegate to the private innerMethod.

These are auto-generated methods which are created by the compiler in some cases (for example when accessing private fields of another class directly, e.g., in case of nested classes).
See also What is the meaning of "static synthetic"? and Synthetic Class in Java.

If you get the relevant .class file (run jar through unzip), and run the .class file through JAD
JAD MyClass.class
then you may find that the output JAD file has decompiled that particular line in a more meaningful way, e.g.
Baz.access$102(Baz.this, true)
shows up in the JAD output as simply
myMemberVaiable = true
where myMemberVaiable is a member of class Baz that you will recognise.

Related

The opens directive in Java 9

I'm reading the draft of the Java 9 specification but this phrase is not clear to me:
The opens directive specifies the name of a package to be opened by the current module. This makes public and protected types in the package, and their public and protected members, be accessible to code in other modules at run time only. It also makes all types in the package, and all their members, be accessible via the reflection libraries of the Java SE Platform.
If the opens makes public and protected accessible at runtime only, what does meaning that all types in the packages area accessible via reflection?
I don't understand the difference between runtime and reflection.
It seems like the opened package makes accessible only public and protected at runtime (via reflection?) and also other packages not specified with type and members accessible vie reflection (also private...).
Let's say you write some code that uses a public class from a library.
import somelibrary.somepackage.SomeClass; // <-- public class from a library.
public class Main {
public static void main(String[] args) {
SomeClass.doSomething();
}
}
You then compile this code, and it compiles fine, since the class you're using is public.
Now, in the next version of the library, the package is added to a module, but not exported. That means that if you try to run your code with this new module on the runtime module path, it would throw an exception because you're trying to access an encapsulated package.
In order to make your code work again, you could use the command line option to open this module to your code, so that it can continue to use the encapsulated package.
Alternatively, the creator of the library could add opens somepackage; to the module definition of the library. That would allow you to run your code using this new version, but not compile with it. I.e. the public and protected members are only accessible at runtime, but there is no reflection involved.
The same goes for when you extend a class, and want to access a protected member of a super class that is in the encapsulated package.
But the opens directive does not change the fact that, if in the next version of a library, a method or field is made private, that you get an IllegalAccessError if you try to use it:
class SomeClass { // <-- the class in the library
public static void doSomething() {
System.out.println("doSomething"); // contrived example code
}
}
...
public class Main {
public static void main(String... args) throws Exception {
SomeClass.doSomething(); // this call compiles fine,
}
}
Then, in the next version of the library doSomething is made private:
private static void doSomething() {...}
And re-compiled. But if you try to run the old version of Main with the new version of SomeClass you get an IllegalAccessError.
In short, opens only works for members that are still public or protected in the new version of the library.
However, in the case of reflection, you can always access a private member, by using setAccessible(true):
public static void main(String... args) throws Exception {
Method m = SomeClass.class.getDeclaredMethod("doSomething");
m.setAccessible(true);
m.invoke(null); // works Fine
}
So in the case of reflection, opens would also make encapsulated private members accessible again.
A package opened by a module, may be qualified or unqualified.
The opens directive in a module declaration declares a package to be
open to allow all types in the package, and all their members, not
just public types and their public members to be reflected on by APIs
that support private access or a way to bypass or suppress default
Java language access control checks.
--Documentation

Why does compiling a class containing static nested classes create a new .class file named "EnclosingClass$1"? [duplicate]

This question already has answers here:
Why is an anonymous inner class containing nothing generated from this code?
(5 answers)
Closed 7 years ago.
In the below code :
class EnclosingClass
{
public static class BiNode extends Sub.IBiLink { }
private static class Sub
{
private static class IBiLink
{
}
}
}
On compiling along with other .class files, I also see a file named "EnclosingClass$1.class" .Why has this been automatically created? Whats going on?
First have a look at the class access and propery modifier table from the JVM specifications.
Notice the ACC_SYNTHETIC flag which interpretation specify that it is not present in the source code (in simplier words, it will be added when the class is generated by the compiler).
Let's have a look at the bytecode of EnclosingClass$1.class (note that I will paste only the part that matter).
javap -v EnclosingClass$1.class
produce the following result
Classfile /C:/Users/jfrancoiss/Desktop/Nouveau dossier/EnclosingClass$1.class
Last modified 2015-03-31; size 190 bytes
MD5 checksum 5875440f1e7f5ea9a519d02fbec6dc8f
Compiled from "EnclosingClass.java"
class EnclosingClass$1
minor version: 0
major version: 52
flags: ACC_SUPER, ACC_SYNTHETIC
Notice that the access flags of the class contains ACC_SYNTHETIC.
The ACC_SYNTHETIC flag indicates that this class or interface was
generated by a compiler and does not appear in source code.
An other option to make sure the generated class is synthetic is to compile as
javac -XD-printflat EnclosingClass.java
which would produce
/*synthetic*/ class EnclosingClass$1 {
}
Great, but why generate a synthetic class ?
The Java reflection tutorial can help us understand this. Have a look at the comments in the SyntheticConstructor class
public class SyntheticConstructor {
private SyntheticConstructor() {}
class Inner {
// Compiler will generate a synthetic constructor since
// SyntheticConstructor() is private.
Inner() { new SyntheticConstructor(); }
}
}
So according on the comment, the synthetic class EnclosingClass$1.class was created because IBiLink was private.
Once again, the java reflection tutorial specify at this point
Since the inner class's constructor references the private constructor
of the enclosing class, the compiler must generate a package-private
constructor.
In our case, we do not see explicitely any constructor call, but we have this line
public static class BiNode extends Sub.IBiLink { }
Let's try compiling this code and see what happen
class EnclosingClass
{
//public static class BiNode extends Sub.IBiLink { }
private static class Sub
{
private static class IBiLink
{
}
}
}
No EnclosingClass$1.class generated.
More details noticed when debugging
Change
private static class IBiLink
to
protected static class IBiLink
notice that when compiling, EnclosingClass$1.class is not created.
why does protecting the class did not generate a synthetic class ?
Simply because when protecting the class, you implicitely get access to each of the super classes.
Why don't eclipse compiler generate a synthetic class ?
Eclipse use it built-in compiler, which you can configure it severity level.
By default, Access to a non-accessible member of an enclosing type is set to ignore as you can see on this image.
Change it for example to warning and you will get the following message.
which let me believe that eclipse, altought does not create an other class, will emulate it to simulate the synthetic member.

instantiating a Scala class using reflection Java's `newInstance`

For some special use-case I have a small utility to load Java classes from jars using a dynamic class loader DynamicClassLoader. This works fine for Java classes contained in jars. Loading Scala classes from a jar also works without problems. However, instantiating the loaded Scala class leads to the following exception. It looks like the Scala class has private default constructor? Note the compiled Scala class name ending with $
java.lang.IllegalAccessException: Class XXX can not access a member of class ScalaClassYYY$ with modifiers "private"
The snippet below illustrates the idea of what I'm trying to achieve and gives a bit more context. The exception happens at the annotated line:
// deploy and register the new code
byte[] jarBytes = (byte[]) ((Object) message.getAttachment("jar"));
String registerClassName = message.getAttachment("register");
logger.debug("the register is '" + registerClassName + "'");
DynamicClassLoader loader = new DynamicClassLoader(jarBytes);
Class<?> registerClass = loader.lookUp(registerClassName);
// ===> this is where the java.lang.IllegalAccessException happens
IRegisterExecutor registerExecutor = (IRegisterExecutor) registerClass.newInstance();
registerExecutor.register();
Any ideas how to fix?
Obviously, you need to make the default constructor public (it won't work for Java classes without a public default constructor either). E.g.
class ScalaClassYYY() {
...
}
or if you want primary constructor to take some arguments,
class ScalaClassYYY(arg1: Int) {
def this() = this(0)
}
But from
Note the compiled Scala class name ending with $
it seems like you are actually trying to instantiate a Scala object:
object ScalaClassYYY { ... }
In this case, you shouldn't create a new instance and instead use the existing one:
(IRegisterExecutor) registerClass.getField("MODULE$").get(null);
EDIT:
I don't see in your answer how you add a default public constructor to a Scala class that does NOT require any parameters.
A class (not an object) that doesn't require any parameters has a default public constructor already (my first example).
Actually in Java all classes by default offer a public default constructor
No. Only those classes which have no constructors which take arguments.
remove the "(it won't work for Java classes without a public default constructor either)" because it is wrong
The documentation for Class.newInstance() says
IllegalAccessException - if the class or its nullary constructor is not accessible.
So I am pretty sure it's right. If it does work for Java classes without a public default constructor, this seems to be a major bug in the class loader you use. You can test it with a Java class which looks like this:
public class TestClass implements IRegisterExecutor {
public TestClass(int dummy) {}
// some implementation for IRegisterExecutor methods to get it to compile
}

$ symbol in .class files

I have a program called MyProgram.java. I want to run it from different directory which will be run on another machine. So I made a directory and copied MyProgram.class file and made a .bat file that runs it (Run.bat) which includes the command: #java MyProgram.
This didn't work, I had to copy SPVerification$1.class that was generated from Eclipse in order to make it work.
What is this XXX$1.class files and why do I need them beside the XXX.class file in order to run an application?
If your .java file have inner/nested classes , post compilation those are generated as Yourclass$xxx.class files by the java compiler.
Inner class definitions produce additional class files. These class
files have names combining the inner and outer class names, such as
MyClass$MyInnerClass.class. - Source
Example (edit)
Considering following Class definition
// MyClass class
public class MyClass{
// Inner class Test1
class Inner1 {
}
// Inner class Test2
class Inner2{
}
public static void main(String [] args) {
// Anonymous inner class 1
new Object() {
};
// Anonymous inner class 2
new Object() {
};
System.out.println("Bunch of $ files :)");
}
}
Will generate these following Files
MyClass.class
MyClass$Inner1.class
MyClass$Inner2.class
MyClass$1.class
MyClass$2.class
They are anonymous inner classes. In other words, when you have a piece like
class OuterClass {
// ...
void method() {
Thread t = new Thread(new Runnable() {
// ... code implementing Runnable interface ...
});
// ... code to use t or whatever
}
}
That generates anonymous inner class, in this case implementing the Runnable interface, and compiled code of that class goes to a OuterClass$<number>.class file. You can have more than one such class, with increasing number in the .class file name.
Note that syntax is exactly the same even if you extend a class with the anonymous inner class, instead of implementing an interface. This is a slightly different from creating named classes, where you need to use implements and extends as appropriate.

Instantiate nested static class using Class.forName

I have a nested static class like:
package a.b
public class TopClass {
public static class InnerClass {
}
}
I want to instantiate with Class.forName() but it raises a ClassNotFoundException .
Class.forName("a.b.TopClass"); // Works fine.
Class.forName("a.b.TopClass.InnerClass"); // raises exception
TopClass.InnerClass instance = new TopClass.InnerClass(); // works fine
What is wrong in my code?
Udo.
Nested classes use "$" as the separator:
Class.forName("a.b.TopClass$InnerClass");
That way the JRE can use dots to determine packages, without worrying about nested classes. You'll spot this if you look at the generated class file, which will be TopClass$InnerClass.class.
(EDIT: Apologies for the original inaccuracy. Head was stuck in .NET land until I thought about the filenames...)
try
Class.forName("a.b.TopClass$InnerClass");
Inner classes are accessed via dollar sign:
Class.forName("a.b.TopClass");
Class.forName("a.b.TopClass$InnerClass");
Inner class is always accessed via dollar sign because when java compiler compile the java source code file it generates .class file(byte code).
if there is only one class for example Hello.java and this class is an outer class then java compiler on compilation generate Hello.class file but if this class has an inner class HelloInner then java compiler generates d Hello$HelloInner.class(byte code).
so bytecode always looks like for following snippet with name Outer.java:
public class Outer
{
public var;//member variable
Outer()//constructor
{
}
class Inner1
{
class Inner2
{
}
}
}
so byte code is:Outer$Inner1$Inner2.class
that's why we use $ sign to access inner class .:)

Categories