Can I remove any implicitly imported Java library? - java

Can I remove any implicitly imported Java library?
It may not seem useful.
But I think it may reduce some execution time!

Imports are just syntactic sugar. All they do is let you access things in other packages without having to state their fully qualified name. The code that is produced is exactly the same as if you fully-qualified everything. So there is no runtime performance penalty to having imports.
This also goes for the "implicit imports" (ie: java.lang): you don't pay any price for the classes you don't actually use.

This will have no effect on execution type - I think I'm correct in saying that, by default, classes are only loaded as and when they are needed, not on mass at start-up.
To improve performance you need to profile your application with a tool like Visual VM and address the bottlenecks it identifies (which will never be where you'd expect).

Java doesn't include all of the classes in java.lang.* in your program. The compiler only includes the ones you explicitly use (or are used by classes you use, etc.).

Related

Manually add a method call to a class file?

I need to manually add a method call to a class file without decompiling and recompiling the code because It depends on thousands of other classes and I don't wan't have to do more than is nessescary. I know java but not how class files are made.
Any help is appreciated.
EDIT:
I am not the owner of the source and I need this to work on any computer, which means I cannot redistribute the sources and have them compiled realtime while my patcher is working.
You have the source code, and you have all other classes compiled. So you can recompile just that source file, passing compiled classes as parameters to java compiler with -classpath option.
You should use ASM or Javaassist to manipulate the bytecode. ASM is a little bit more complex and requires you to understand more about the JVM, but it's faster. Javaassist doesn't require you to know much about the JVM's internals.
However, I don't see why you can't just recompile that single sourcefile? If you only need to add this method once, it's very inefficient to learn ASM or Javaassist.
How about subclassing? Then you don't need to touch the sources.
So if you have the source code and want to add some methods into only one class. Then you don't have to worry about other classes even they are dependent on your current modified class. Re-compiling a file doesn't affect other classes. Since the output will be produced at run-time.
If your class is not declared final and the method you are interested is not final, you can extend the class and override just that method.
Just change the source code, recompile ! Everything will work fine. Subclassing won't work .Because Already existing classes won't know about the new subclass until you change their code to use the new subclass instead of old superclass.
For manual editing of classfiles, I'd recommend Krakatau. (Disclosure, I wrote it). It lets you disassemble a classfile, edit it, and reassemble. There are other assemblers out there, but AFAIK, Krakatau is the only one that supports all the weird edge cases in the classfile format.
The main caveat is that Krakatau by default does not preserve certain optional debugging attributes (specifically LineNumberTable, LocalVariableTable, and LocalVariableTypeTable), since there is no simple way to represent them in a human editable format, and failing to edit them when the bytecode changes will result in a verification error. Most likely you don't actually need this though so it shouldn't matter.
The other caveat of course is that you have to understand bytecode. But if you don't, you won't be able to manually edit classfiles anyway.
I got it now! I Created fake source files with the same names/methods but didn't add anything else except for class and method names. That way I only needed to pack the ones that are directly linked to my Class file. But now compiling takes a few milliseconds whereas it used to take around 124s, Lol. Works great!

Can a custom ClassLoader load a class ignoring it's dependencies?

I have a binary class which I want to load, but I don't have it's dependencies.
I still want to load it though, to get it's qualified name.
I understand that I will not be able to use it for anything else (and that is ok), I just need the qualified name.
So is there a way to do this with a custom class loader ?
Thanks,
As for strictly answering the question: see section on symbolic references resolution in the JVM specification. In short: little is guaranteed as to when resolution is performed. I'm not sure what is the precise behaviour of current implementations, but if you go this way, the solution will not be completely reliable, even though it will probably work.
You said you only need its qualified name, though. That's a different story, that's pretty easy, in fact. JVM specification describes in detail the format of the class file. Since you have the binaries, you can extract it directly from the data, bypassing classloading mechanism of the JVM completely. If you don't want to do it by hand, use appropriate tools - ASM comes to mind, with its wonderful, detailed documentation. Some alternatives are BCEL, javassist and CGLIB (no longer maintained).

Deprecating an java JRE method

I would like to mark usage of certain methods provide by the JRE as deprecated. How do I do this?
You can't. Only code within your control can have the #Deprecated annotation added. Any attempt to reverse engineer the bytecode will result in a non-portable JRE. This is contrary to Java's write once, run anywhere methodology.
you can't deprecate JRE methods, but you can add warnings or even compile errors to your build system i.e. using AspectJ or forbid the use of given methods in the IDE.
For example in Eclipse:
Go to Project properties -->Java Compiler --> Errors Warnings, Then enable project specific settings, Expand Deprecated and restrited APIs category
"Forbidden reference (acess rule)"
Obviously you could instrument or override the class adding #Deprecated annotation, but it's not a clean solution.
Add such restrictions to your coding guidelines, and enforce as part of your code review process.
You only can do it, if and only if you are building your own JRE! In that case just add #Deprecated above the corresponding code block! But if you are using Oracle's JRE, you are no where to do so!
In what context? Do you mean you want to be able to easily configure your IDE to inhibit use of certain API? Or are you trying to dictate to the world what APIs you prohibit? Or are you trying to do something at runtime?
If the first case, Eclipse, and I assume other IDEs, allow you to mark any API as forbidden, discouraged, or accessible at the package or class level.
If you mean the second, you can't, of course. That would be silly.
If you are trying to prohibit certain methods from being called at runtime, you can configure a security policy to prevent code loaded from specified locations from being able to call specific methods that check with the SecurityManager, if one is installed.
You can compile your own version of the class and add it to the boot class path or lib/ext directory. http://docs.oracle.com/javase/tutorial/ext/basics/install.html This will change the JDK and the JRE.
In fact you can remove it for compiling and your program won't compile if it is used.
Snihalani: Just so that I get this straight ...
You want to 'deprecate methods in the JRE' in order to 'Making sure people don't use java's implementation and use my implementation from now on.' ?
First of all: you can't change anything in the JRE, neither are you allowed to, it's property of Oracle. Uou might be able to change something locally if you want to go through the trouble, but that 'll just be in your local JRE, not in the ones that can be downloaded from the Oracle webpage.
Next to that, nobody has your implementation, so how would we be able to use it anyway? The implementations provided by Oracle do exactly what they should do, and when a flaw/bug/... is found it'll be corrected or replaced by a new method (at which point the original method becomes deprecated).
But, what mostly worries me, is that you would go and change implementations with something you came up with. Reminds me quite lot of phishing and such techniques, having us run your code, without knowing what it does, without even knowing we are running your code. After all, if you would have access to the original code and "build" the JRE, what's to stop you from altering the code in the original method?
Deprecated is a way for the author to say:
"Yup ... I did this in the past, but it seems that there are problems with the method.
just in order not to change the behaviour of existing applications using this method, I will not change this method, rather mark it as deprecated, and add a method that solves this problem".
You are not the author, so it isn't up to you to decide whether or not the methods work the way they should anyway.

Possible to use two java classes with same name and same package?

Is it possible to import and use two different classes with the same name and package in java?
For example, let's say I have two classes named "com.foo.Bar" that are slightly different. I'd like to be able to use both, but I have a restriction (because of stupid reflective crap) that forces me to keep the names and packages the same.
Is there some feature of java that would allow me to import and isolate each of these classes?
To elaborate, I changed my avro schemas in ways that they shouldn't have ever been changed (oops!) and now I'd like to go back and change the old avro files that can't be read with my new schema into files that can be read by my new schema. Avro seems to force you to use a specific class and package name to load the files.
Yes there is. You would need to implement your own Classloader and play some games to be able to access both during runtime.
I'm sure this is possible, because I ran into a very hard to debug issue where someone had a weird Classloader in their product that was messing up loading libraries and providing 2 different versions of the same file from 2 different versions of the library.
However, this sounds like an INCREDIBLY bad idea. I'd go back and find a different way of fixing your issue. This will only bring you heartache in the long run. Heck, it probably already is, as you investigate class loaders.
EDIT: To be specific, you cannot "import" both. But you can access both at runtime.
No, java packages are used precisely to avoid that problem.
Yes it is. It does require you to make your own ClassLoader, though
I had made a demo of that on github to!
If you really most definitely must do something like this, you can achieve it by using different classloaders and possibly reflection.
This is not the way Java works and it's not allowed on purpose - you shouldn't be doing stupid things which will screw up things for you.
There are no namespaces in Java, only in C#, so I assume you mean packages. There can only be one fully qualified name per project.
Technically it can be done using some low-level trickery such as rewriting the byte-level code. As far as I know the different java crypter/encrypters work like that - they have a lot of classes called A.class B.class C.class etc.
It sounds to me like you need to define your method signatures in an interface called com.foo.Bar. Then provide two different concrete implementations of the interface (say, com.foo.DefaultBar, and com.foo.SpecialBar). This way, you can program against the interface type, and switch between the two different implementations as required.
Can you elaborate on what you mean by "reflective crap"? That may provide insight into your exact issue.
Don't mess with the class loader or any other low level trickery. The best way to solve such issues it to have a clear design in the first place that anyone can understand.
As already mentioned writing your own Classloader or additionally use a OSGi framework like Equinox which does the classloading for you

How to determine which classes are used by a Java program?

Is there any tool that lists which and when some classes are effectively used by an app or, even-better, automatically trims JAR libraries to only provide classes that are both referenced and used?
Bear in mind that, as proven by the halting problem, you can't definitely say that a particular class is or isn't used. At least on any moderately complex application. That's because classes aren't just bound at compile-time but can be loaded:
based on XML config (eg Spring);
loaded from properties files (eg JDBC driver name);
added dynamically with annotations;
loaded as a result of external input (eg user input, data from a database or remote procedure call);
etc.
So just looking at source code isn't enough. That being said, any reasonable IDE will provide you with dependency analysis tools. IntelliJ certainly does.
What you really need is runtime instrumentation on what your application is doing but even that isn't guaranteed. After all, a particular code path might come up one in 10 million runs due to a weird combination of inputs so you can't be guaranteed that you're covered.
Tools like this do have some value though. You might want to look at something like Emma. Profilers like Yourkit can give you a code dump that you can do an analysis on too (although that won't pick up transient objects terribly well).
Personally I find little value beyond what the IDE will tell you: removing unused JARs. Going more granular than that is just asking for trouble for little to no gain.
Yes, you want ProGuard. It's a completely free Java code shrinker and obfuscator. It's easy to configure, fast and effective.
You might try JarJar http://code.google.com/p/jarjar/
It trims the jar dependencies.
For most cases, you can do it quite easily using just javac.
Delete you existing class files. Call javac with the name of your entry classes. It will compile those classes necessary, but no more. Job done.

Categories