PHP like Autoloader in Java - java

Does the Java Interpreter support an Autoloader-Function or a possibility to extend his "Looking for a class"-function?
In PHP there is a function called spl_autoload_register (see http://www.php.net/manual/en/function.spl-autoload-register.php for details ), which forces the interpreter to execute my own callback function when he is looking for a missing class. In my callback function I can include the file with the expected class.
The background-idea is that I'd like to switch dynamically between software-layers.
For example:
If class x_L2 exists in layer 2 then class x_L1 in the underlying layer 1 should be ignored. Actually I solved this issue with a general mirror class x, which have to inherit from the class in the highest available layer. But this way is error-prone when you have to maintain hundreds of classes.
Thanks in advance.

This can be done by using a different class loader such as URLClassLoader. Then, you would get your classes from this class loader with loadClass. Yes, it also supports local and remote resources.

You can write your own ClassLoader subclass, and use its loadClass() instead of the default one.

It seems you are trying to write a custom class loader ?
IBM has good documentation on that to help you on that.

Classes are identified by their package, as classes can be identified by namespaces in PHP.
In order to use a specific class, you can simply use a qualified name.
public mypackage.mysubpackage.Myclass myInstanceofMyClass;
Or you could import only the needed class :
import mypackage.mysubpackage.Myclass;
You cannot have a class having the same name as another class in the same package. That's a duplicate définition of a type. I am not aware of a callback function for inclusion.

Related

Different behaviour of Class literal and Class.forName for package local classes

Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.

How to programmatically know who (other java files/classes) is using my java class?

I want to get a list of all java class which are dependent on my class. Is there a library which exposes intended API? API is expected to return list of java classes using my java class.
You would probably use Reflection API..
They were specifically made for this kind of problems.. They allow to get information about classes at runtime..
You can get: -
All the methods
All the derived classes
All the variables.
And many more information..
You can see Class.getClasses() and Class.getDeclaredClasses()
See some more examples
Reflection can tell you whether a specific class extends your class, uses your class as a field, takes your class as a parameter, or returns your class from a method. However if the use of your class is method confined then reflection will not work.

Classloader variants and usage in Java

I understand that java.lang.ClassLoader is generally the classloader I extend (when needed). Also, when I see the custom classloaders of tomcat, Jetty etc extend from java.lang.ClassLoader.
I'm curious to understand the purpose and usage of com.sun.org.apache.bcel.internal.util.ClassLoader.
Can someone help me understand it ?
com.sun.org.apache.bcel.internal is just a repackaging of Apache BCEL. In particular, the class we're interested in (ClassLoader) is documented here...
Drop in replacement for the standard class loader of the JVM. You can use it in conjunction with the JavaWrapper to dynamically modify/create classes as they're requested.
This class loader recognizes special requests in a distinct format, i.e., when the name of the requested class contains with "$$BCEL$$" it calls the createClass() method with that name (everything before the $$BCEL$$ is considered to be the package name. You can subclass the class loader and override that method. "Normal" classes class can be modified by overriding the modifyClass() method which is called just before defineClass().
judging by the "bcel" part of the package name that classloader doesnt just load classes, it alters the bytecode on the fly (see the bcel homepage).
edit: some more info on what they do with it can be found here : "BCEL is used internally by XSLTC to "compile" XSLT stylesheets into bytecodes for execution"

Can you extend Abstract Java Classes from JavaScript?

I'm working on a project that makes really heavy use of the javax.script.* packages. I have a situation where I would like to create JavaScript objects that extend an Abstract Java Class, much like you can use Invocable.getInterface to make JavaScript objects that implement Java interfaces. Is this possible? And, if so, how do you do it?
Yes, you can; previous poster is wrong. See the documentation for JavaAdapter.
Unless you want to go the route of generating bytecode at runtime (using BCEL as below) then no. You can do it with interfaces using proxy classes but there is no equivalent for abstract classes.
If you really want to try BCEL, your best strategy is to do this:
Write a method that uses BCEL to generate a byte[] of bytecode for a new class that extends the abstract class and delegates every abstract method to JavaScript.
Define a naming convention that relates abstract classes to the wrapper, e.g. foo.MyAbstractClass corresponds to foo.MyAbstractClassDynamicLangWrapper.
Roll a ClassLoader that implements findClass to recognize that naming convention and to generate the class bytes and calls defineClass
Make sure your scripting language uses your custom classloader to resolve class names in scripts. I think in Rhino you use setApplicationClassLoader but I'm not sure.

Hiding classes in a jar file

Is it really impossible to hide some classes in a jar file?
I wanted not to allow direct instantiation of the classes to keep it more flexible. Only the factory (or a facade) should be visible of this jar.
Is there any other way than solve this problem than creating two projects?
(Two projects: the first one contains the classes (implementation) and the other one references to the first one and contains the factory; later only the second one will be referenced)
I'm understanding you're not looking to hide the actual classes, just prevent their construction outside a factory class. This I think can be quite easily achieved by using package private (default) visibility in the class constructors. The only limitation is that you'll need to have the classes and the factory in the same package so in a medium to large codebase things may get unnecessarily complex.
If I understand your question correctly, you would like to make sure that users of your library are forced to use your factory to instantiate their objects rather than using the constructors themselves.
As I see it there are two possibilities, one of which is silly but usable in few, specific cases, and the other one is the most practical and probably most commonly used way of doing it.
You could make all your classes into
private inner classes of the
factory. This would work if you had
one factory per class, but is hardly
workable if you have a lot of
different classes being managed
through one factory.
You could use the protected access modifier to
restrict access to your class
constructors. This is common
practice when using the factory
pattern.
I think you will have either compiler failure or warning if your public factory method try to return something which is "hidden".
No, you can not hide a public class without reimplementing your own ClassLoader or using OSGi or anything similar.
What you can do is to separate interface api from the implementation, e.g. have one project which contains only the interfaces and another porject which contains the implmentations. However, you still cannot hide the implementation classes.
Obfuscation can help you somehow.
With standard classloaders and plain old jar files, this is not possible. OSGi has this concept of making visible only some packages to another bundle(i.e. separation of public api and internal implementation).
If you are using eclipse, you may enforce such rules with this
If I understand you correctly when you say "not to allow direct instantiation of the classes to keep it more flexible", a properly executed facade pattern will handle this.
Restrict the constructors of all the classes you want to hide to package scope. Open the facade class to public scope.
http://mindprod.com/jgloss/packagescope.html
"If you have a variable or method in
your class that you don’t want clients
of your class directly accessing,
don’t give it a public, protected or
private declaration. Due to an
oversight in the design of Java, you
can’t explicitly declare the default
“package” accessibility. Other members
of the package will be able to see it,
but classes outside the package that
inherit from yours, won’t. The
protected accessibility attribute
offers slightly more visibibily. A
protected method is visible to
inheriting classes, even not part of
the same package. A package scope
(default) method is not. That is the
only difference between protected and
package scope. "
There are two solutions to your question that don't involve keeping all classes in the same package.
The first is to use the Friend Accessor/Friend Package pattern described in (Practical API Design, Tulach 2008).
The second is to use OSGi. There is an article here explaining how OSGi accomplishes this.
Related Questions: 1, 2, 3, and 4.
You can do such magics with a custom class loader but:
the correct separation will be available only in a project staffed with your class loader;
it's really doubtful that the effort to create such loader is worthy.
In such situations I would do something similar to what we may see in the standard Java. E.g.you see javax.xml.stream.XMLInputFactory but somewhere you have com.sun.xml.internal.stream.XMLInputFactoryImpl. It is perfectly compilable if you write:
new com.sun.xml.internal.stream.XMLInputFactoryImpl()
though you will hardly do it :-) With a system property you may control the actual implementation that is being loaded. To me such approach is fine in many situations.
I hope I have understood your question correctly ;)
Cheers!

Categories