Frustrated with the damn awful API provided by WebSphere Admin Server, I'm writing my own Java DSL wrapper. My jython files now simply read:
from my.package import MyDSL
config = MyDSL(AdminConfig, AdminTask)
config.goGoGadgetSkates() # or something like that
The essential part is that I send through the (#%$$!##) god objects AdminConfig and AdminTask so that the DSL can use them to perform operations in WAS.
In order to compile the DSL I need to include the class files for this two objects. I find them by first setting the constructor as:
public MyDSL(Object a, Object b) {
System.out.println(a.getClass());
System.out.println(b.getClass());
}
The output showed that the AdminConfig object is an instance of com.ibm.ws.scripting.AdminConfigClient. I easily located the jar that contains this class and all is well.
But AdminTask is an instance of com.ibm.ws.scripting.adminCommand.AdminTask. Despite being present at runtime, this class does not exist anywhere in my classpath or indeed anywhere on my computer's hard drive.
I can only assume com.ibm.ws.scripting.adminCommand.AdminTask is constructed magically by WSAdmin in the jython layer. Perhaps it is defined as a python class?
Before I resort to reflection, can someone please explain where com.ibm.ws.scripting.adminCommand.AdminTask might live and how I might extract a copy of the class file?
The AdminConfigClient class is not API/SPI, so you are creating a fragile infrastructure by relying on that class. The API/SPI entry point is ConfigServiceFactory.
The AdminTask object is backed by the data in CommandMgr. It should be possible to use CommandMgr to do anything you can do with AdminTask.
Related
I am currently learning about Reflection and I have seen most of the similar posts to my question on stack however, I don't feel they fully answer my question on it.
I want to know if I have a package in Eclipse can I use Reflection to iterate through the classes in the package to find which one implements interface. There is only 1 interface so either they implement it or don't.
Could anyone provide a basic clear example as to how I may go about this? I have been told by some that this is just not possible whilst other people say it is possible using Reflection.
Thank you to any one who could help clear this matter.
Reflection API does not provide directly facility to iterate over classes in specific package. It concentrates on discovery of class once you have it.
To achieve what you want to have to read the class path of your application, iterate over the class path, open jars and go into directories, find files that end with *.class and get them as resource like getResource(full_class_name) or get it directly as class using Class.forName().
This method has a limitation: you will not see classes loaded by custom class loaders.
Unless this is an exercise I'd recommend you to use Reflections library that does everything you need and (probably) even more... :)
Some more details
Java system property "java.class.path" contains class path of your application separated with ; on Windows and : on Unix.
So, this is the way you can get list of class path elements:
System.getProperty("java.class.path").split(File.pathSeparator)
Here is some code sample that can help you to start:
for (String cpElement : System.getProperty("java.class.path").split(File.pathSeparator)) {
File cpFile = new File(cpElement);
if (!cpFile.exists()) {
continue;
}
if (cpFile.isDirectory()) {
findClassesInDirectory(cpFile);
} else {
findClassesInArchive(cpFile);
}
}
Etc, etc. I am leaving implementation of findClassesInDirectory() and findClassesInArchive() for you. Nice exercise. Have fun.
have you heard of guava-libraries for Java.
They provide useful utilities regarding reflection.
For your specific problem, I would have a look a the TypeToken and the method getTypes().
Good luck
yes you can so it. But with eclipse its more of an AST tree translation and not reflections. See if you want to iterate over source code and see which source file implements the interface you probably need AST tree walkers to do that. But on the other hand if you want to introspect at runtime the class files in a given package or a folder which implement the said interface then you need Reflections to do that. Either way its doable. I cant give you the code to try that out as a little time with Google will give you the answers you need though not all at the same place.
Reflection does not provide all operations for a total inspection.
For a known class one can get the physical URL of a class SomeClass using:
CodeSource codeSource = SomeClass.class.getProtectionDomain().getCodeSource();
if (codeSource == null) {
// Run-time class; URL into the rt.jar.
} else {
URL url = codeSource.getLocation();
// "file:/.... /classes/.../SomeClass.class"
// "jar:file:/... /someJar.jar!/.../SomeClass.class"
}
For Java run time classes (rt.jar) codeSource will be null.
On the URL of the jar you can open a (zip) file system, and walk through folders as any real file system.
You'll probably want to inspect classes without $ in the name (embedded, generated anonymous classes): only fileName.matches("[^$]+\\.class").
I have a problem in my Java project, I have a bunch of projects (for example A, B, C…) that happen to have a Tools class in a tool folder in a path such as src.tool.Tools, the same path and same class name for all of them.
Now, I have my project Z that has in its build path all of these projects (A, B, C…). How can I make sure that when I import one Tool class I am importing the one I really need?
More complicated, if in A.Tool I have a method such as public int tool(){return 1} and in B.Tool another method such as public int tool(){return 0} How can I make sure I call the function I really want?
Thanks for all!
Three options:
The risky way: make sure then class you really want comes first in the classpath and every classloader involved, processes them in that order. This can break extremely easy with very confusing results. You can't access multiple versions of the class, you can only control which on you get. Don't do this.
The complicated way: Create classloaders for each project you depend on and adress the specific classloader to load the class. That is a lot of work to get right, you might be able to use OSGI for this. Do this only if your main aim is to learn about class loaders.
The simple and right way: Refactor your projects so all packages in each project have the project name (or some representation of it) in the package name. This makes each package name unique and you can access classes without any problem (possibly using the full qualified class name if you have to use multiple Tool classes in one place) While you're at it, you might as well rename the Tool classes that actually describes the purpose, class and package names like "Util", "Tool" or "Misc" are really really bad code smells.
Probably using a user-defined class loader:
Every user-defined class loader is an instance of a subclass of the
abstract class ClassLoader. Applications employ user-defined class
loaders in order to extend the manner in which the Java Virtual
Machine dynamically loads and thereby creates classes. User-defined
class loaders can be used to create classes that originate from
user-defined sources. For example, a class could be downloaded across
a network, generated on the fly, or extracted from an encrypted file.
I don't think it is possible to do what you want. If you have three classes all called "src.tool.Tools", Java doesn't care what jar file you loaded them from. If all three projects (which I am assuming means jar files) have this same class, Java will have a clash and you can't predict which Tools it is going to load.
The only way to make sure the correct one is getting called is making sure the other two are not in the classpath.
There is a hack solution to your problem. You could create a new ClassLoader for each project and ask the ClassLoader for the desired project for the Tools class. Then using reflection you can instantiate it and call the method. Since each project is in its own ClassLoader, the three Tools classes won't clash anymore.
Ex:
URLClassLoader a = new URLClassLoader(aJar.toURL(), getClass().getClassLoader());
Class toolsClass = Class.forName("src.tool.Tools", true, a);
Method m = toolsClass.getDeclaredMethod("tool");
Object i = toolsClass.newInstance();
Object result = m.invoke(instance);
(URLClassLoader example pulled from How should I load Jars dynamically at runtime?)
Assuming that your projects A,B,C each have different package namespaces, e.g. com.you.A, com.you.B, etc, your Tools class will now be available in multiple locations like com.you.A.tool.Tools, com.you.B.tool.Tools, etc.
So when in project Z you create an instance of Tools class, you can specify the exact class to use while declaring the object reference variable.
private com.you.A.tool.Tools toolsFromA;
private com.you.B.tool.Tools toolsFromB;
calling toolsFromA.tool() will return 1 and calling toolsFromB.tool() will return 0.
If one writes two public Java classes with the same case-insensitive name in different directories then both classes are not usable at runtime. (I tested this on Windows, Mac and Linux with several versions of the HotSpot JVM. I would not be surprised if there other JVMs where they are usable simultaneously.) For example, if I create a class named a and one named A like so:
// lowercase/src/testcase/a.java
package testcase;
public class a {
public static String myCase() {
return "lower";
}
}
// uppercase/src/testcase/A.java
package testcase;
public class A {
public static String myCase() {
return "upper";
}
}
Three eclipse projects containing the code above are available from my website.
If try I calling myCase on both classes like so:
System.out.println(A.myCase());
System.out.println(a.myCase());
The typechecker succeeds, but when I run the class file generate by the code directly above I get:
Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)
In Java, names are in general case sensitive. Some file systems (e.g. Windows) are case insensitive, so I'm not surprised the above behavior happens, but it seems wrong. Unfortunately the Java specifications are oddly non-commital about which classes are visible. The Java Language Specification (JLS), Java SE 7 Edition (Section 6.6.1, page 166) says:
If a class or interface type is declared public, then it may be accessed by
any code, provided that the compilation unit (§7.3) in which it is declared is
observable.
In Section 7.3, the JLS defines observability of a compilation unit in extremely vague terms:
All the compilation units of the predefined package java and its subpackages lang
and io are always observable. For all other packages, the host system determines which compilation units are observable.
The Java Virtual Machine Specification is similarly vague (Section 5.3.1):
The following steps are used to load and thereby create the nonarray class or
interface C denoted by [binary name] N using the bootstrap class loader [...]
Otherwise, the Java virtual machine passes the argument N to an invocation of a
method on the bootstrap class loader to search for a purported representation of C
in a platform-dependent manner.
All of this leads to four questions in descending order of importance:
Are there any guarantees about which classes are loadable by the default class loader(s) in every JVM? In other words, can I implement a valid, but degenerate JVM, that won't load any classes except those in java.lang and java.io?
If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
Is there any way to make HotSpot load a and A simultaneously? Would writing a custom class loader work?
Are there any guarantees about which classes are loadable by the bootstrap class loader in every JVM?
The core bits and pieces of the language, plus supporting implementation classes. Not guaranteed to include any class that you write. (The normal JVM loads your classes in a separate classloader from the bootstrap one, and in fact the normal bootstrap loader loads its classes out of a JAR normally, as this makes for more efficient deployment than a big old directory structure full of classes.)
If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
Is there any way to make "standard" JVMs load a and A simultaneously? Would writing a custom class loader work?
Java loads classes by mapping the full name of the class into a filename that is then searched for on the classpath. Thus testcase.a goes to testcase/a.class and testcase.A goes to testcase/A.class. Some filesystems mix these things up, and may serve the other up when one is asked for. Others get it right (in particular, the variant of the ZIP format used in JAR files is fully case-sensitive and portable). There is nothing that Java can do about this (though an IDE could handle it for you by keeping the .class files away from the native FS, I don't know if any actually do and the JDK's javac most certainly isn't that smart).
However that's not the only point to note here: class files know internally what class they are talking about. The absence of the expected class from the file just means that the load fails, leading to the NoClassDefFoundError you received. What you got was a problem (a mis-deployment in at least some sense) that was detected and dealt with robustly. Theoretically, you could build a classloader that could handle such things by keeping searching, but why bother? Putting the class files inside a JAR will fix things far more robustly; those are handled correctly.
More generally, if you're running into this problem for real a lot, take to doing production builds on a Unix with a case-sensitive filesystem (a CI system like Jenkins is recommended) and find which developers are naming classes with just case differences and make them stop as it is very confusing!
Donal's fine explanation leaves little to add, but let me briefly muse on this phrase:
... Java classes with the same case-insensitive name ...
Names and Strings in general are never case-insensitive in themselves, it's only there interpretation that can be. And secondly, Java doesn't do such an interpretation.
So, a correct phrasing of what you had in mind would be:
... Java classes whose file representations in a case-insensitive file-system have identical names ...
I tried to add or remove a character from one of the class names and it worked. I feel it's always better to use different class names.
Don't think just about folders.
Use explicit different namespaces ("packages") for your classes, and maybe use folders to match your classes.
When I mention "packages", I don't mean "*.JAR" files, but, just the concept of:
package com.mycompany.mytool;
// "com.mycompany.mytool.MyClass"
public class MyClass
{
// ...
} // class MyClass
When you do not specify a package for your code, the java tools (compiler, I.D.E., whatever), assume to use the same global package for all. And, in case of several similar classes, they have a list of folders, where to look for.
Packages are like "virtual" folders in your code, and apply to all your packages on your classpath, or installation of Java. You can have several classes, with the same I.D., but, if they are in different package, and you specify which package to look for, you won't have any problem.
Just my 2 cents, for your cup of Java coffe
As everyone knows - public java classes must be placed in their own file named [ClassName].java
( When java class X required to be placed into a file named X.java? )
However, we are auto-generating 50+ java classes, and I'd like to put them all in the same file for our convenience. This would make it substantially easier to generate the file(s), and copy them around when we need to.
Is there any way I can get around this restriction? It seems like more of a stylistic concern - and something I might be able to disable with a compiler flag.
If not, what would you recommend?
Can you put wrapper class around your classes? Something like:
public class Wrapper {
public static class A {...}
public static class B {...}
....
}
Then you can access them via Wrapper.A, Wrapper.B.
At the .class level, this is a requirement per the Java spec. Even the inner classes get broken out into their own class file in the from Outer$Inner.class. I believe the same is true at the language level.
Your best bet is to generate the files and make your copy script smart. Perhaps generate them and zip them up. Usually, if you have to move these files around then either everyone has the same generator script OR you distribute them as a JAR.
Is there any way I can get around this restriction?
You can change your generated source code to make it acceptable; e.g. by using nested classes, by putting the generated classes into their own package.
It seems like more of a stylistic concern - and something I might be able to disable with a compiler flag.
It is not just a stylistic concern:
The one file per class rule is allowed by the Java Language Specification.
It is implemented by all mainstream Java compilers.
It is implemented by all mainstream JVMs in the form of the default classloader behavior.
It is assumed by 3rd party Java tools; e.g. IDEs, style checkers, bug checkers, code generation frameworks, etc.
In short, while it would theoretically be legal to implement a Java ecosystem that didn't have this restriction, it is impractical. No such compiler switch exists, and implementing one would be impractical for the reasons above.
The nested class solution is a good one. Another alternative would be to put the generated classes into a separate package (but with separate file) to make them easier to manage.
I wonder if there's an easy way to determine which classes from a library are "used" by a compiled .NET or Java application, and I need to write a simple utility to do that (so using any of the available decompilers won't do the job).
I don't need to analyze different inputs to figure out if a class is actually created for this or that input set - I'm only concerned whether or not the class is referenced in the application. Most likely the application would subclass from the class I look for and use the subclass.
I've looked through a bunch of .Net .exe's and Java .classes with a hex editor and it appears that the referenced classes are spelled out in plaintext, but I am not sure if it will always be the case - my knowledge of MSIL/Java bytecode is not enough for that. I assume that even though the application itself can be obfuscated, it'll still have to call the library classes by the original name?
Extending what overslacked said.
EDIT: For some reason I thought you asked about methods, not types.
Types
Like finding methods, this doesn't cover access through the Reflection API.
You have to locate the following in a Reflector plugin to identify referenced types and perform a transitive closure:
Method parameters
Method return types
Custom attributes
Base types and interface implementations
Local variable declarations
Evaluated sub-expression types
Field, property, and event types
If you parse the IL yourself, all you have to do is process from the main assembly is the TypeRef and TypeSpec metadata, which is pretty easy (of course I'm speaking from parsing the entire byte code here). However, the transitive closure would still require you process the full byte code of each referenced method in the referenced assembly (to get the subexpression types).
Methods
If you can write a plugin for Reflector to handle the task, it will definitely be the easiest way. Parsing the IL is non-trivial, though I've done it now so I would just use that code if I had to (just saying it's not impossible). :D
Keep in mind that you may have method dependencies you don't see on the first pass that neither method mentioned will catch. These are due to indirect dispatch via the callvirt (virtual and interface method calls) and calli (generally delegates) instructions. For each type T created with newobj and for each method M within the type, you'll have to check all callvirt, ldftn, and ldvirtftn instructions to see if the base definition for the target (if the target is a virtual method) is the same as the base method definition for M in T or M is in the type's interface map if the target is an interface method. This is not perfect, but it is about the best you can do for static analysis without a theorem prover. It is a superset of the actual methods that will be called outside of the Reflection API, and a subset of the full set of methods in the assembly(ies).
For .NET: it looks like there's an article on MSDN that should help you get started. For what it's worth, for .NET the magic Google words are ".net assembly references".
In Java, the best mechanism to find class dependencies (in a programmatic fashion) is through bytecode inspection. This can be done with libraries like BCEL or (preferably) ASM. If you wish to parse the class files with your own code, the class file structure is well documented in the Java VM specification.
Note that class inspection won't cover runtime dependencies (like classes loaded using the service API).