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).
Related
In software development we are all using the libraries by software providers. Consider in class A there are four functions viz., x,y,z. I just want my development team to avoid using the function x. So instead of telling them not to use, I found an idea. Inherit the class and override all the functions and for the function x an unsupportedmethod exception is thrown and for the rest I'm calling the super methods. There also I found a problem, developers can use the base class A directly, how to avoid the class A being used directly. I found a similar functionality in OSGi, the lib bundles can be brought in and then not exported and so on. Is there are any way to achieve this is java?
I suppose code reviews exist for these reasons. Consider situation where you can not edit the source of a third party, what would you do ? Like Siddharth says, sub class it and throw a meaningful exception and document it with a clear reasons. If someone is using base class even after that, mostly it may not out of ignorance,but it may out of curiosity. That kind of thing can be appreciated personally and for learning, but for the project sake developer has to follow the guidelines.
I think simply telling your developers what to do is preferred over a complex software solution. Sometimes the simple thing is better.
But, if you insist on going down this path, you can enforce your architecture standards using aspects if you're a Spring user. Weave the offending methods with an aspect that throws an exception if they're called.
You can edit library class file in hex editor and modify its access modifier from public to package private. Also you can rename it and then use inheritance to wrap this class. Here you can find class file specification. Once I've tried this technique to substitute jdbc driver class with wraper class that provide some additional logging and other useful tricks.
There is a variety of tools that check source code for adherence to certain rules, such as formatting, dead code, naming conventions for variables etc. Popular ones for Java include the Maven Enforcer plugin, checkstyle and PMD.
These might allow you to write a rule that forbids certain method calls. Then you could check automatically at compile time. As far as I can tell, unfortunately none of the tools above support "illegal method calls" out-of-the-box; however, at least for PMD writing new checks is fairly simple.
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
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.).
A customer requires a preview of a new feature of our product. They asked to have that feature sent to them in a jar file (like a patch). There's no problem with including the new classes in said jar file. However, an existing class was modified, which is needed to integrate the new feature. They just want to add this new jar file without having to update the core classes of our product. So, the question is: is it possible to override an already existing class using a separate jar? If so, how?
Thanks in advance.
There's a chance it'll work if you put the new jar earlier in the classpath than the original jar. It's worth trying, although it still sounds like a recipe for disaster - or at least, really hard to debug issues if somehow both classes are loaded.
EDIT: I had planned to write this bit earlier, but got interrupted by the end of a train journey...
I would go back to the customer and explain that while what they're asking is possible, it may cause unexpected problems. Updating the jar file is a much safer fix, with much less risk. The phrases "unexpected problems" and "risk" are likely to ring alarm bells with the customer, so hopefully they'll let you do the right thing.
Yes and no, it depends on your environment.
If you use, for example, OSGi and have your versions under control, it's just a matter of installing a new bundle with the exported package at a higher version (assuming your version ranges are lenient enough).
If you use plain old Java with no fancy custom class loading, you should be good to go putting it earlier on your class path (as others already mentioned).
If you do have custom class loading, you'll need to make sure that all the classes that your 'patched' class needs, and indeed the entire transitive dependency hull, is visible from the class loader which is loading the patched version, which might mean you need to ship the entire application, worst case.
All of the answers that stipulate putting the updated classes before the ones they are replacing in the classpath are correct, only provided the original JAR is not sealed or signed.
Yes, it may be possible, by putting it earlier on the classpath than your original jar. However, relying on the ordering of your classpath is not always going to lead to happiness. I'm not sure if it is even documented in the Java Language Spec; if not, then it's going to break for different JVMs and even different versions of the same JVM.
Instead, consider quoting a realistic time frame to integrate the new feature into the current codebase. This is perhaps not the answer you're looking for.
Probably more than you need for this specific case, but in generally if you just want to tweak or augment an existing class you can also use AspectJ with load-time weaving.
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.