views:

435

answers:

3

I wanted to create add to my jdk6\jre\lib\security\java.policy file an interdiction to create some classes that are blacklisted by appengine. For example I want my local jvm to throw an exception when the application tries to instantiate javax.naming.NamingException.

It is possible?

I will try to explain my specific problem here. Google offers an service (GAE-google app engine) that has some limitations on what classes can be used. For example doesn't instantiate JNDI classes that are in javax.naming package. They also offer an testing server that can be used to tests this application on my machine, but this server allows such classes and can exacute the code. You find out that you used a blacklisted class only after you upload your application to google. I was thinking if such class blacklist enforcement couldn't be done on the development jvm. Else i'm thinking that this would be easy they might already provide such a policy file.

A: 

The Java documentation lists all possible policy permissions here: http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html

Class creation / loading is not mentioned, so I believe you cannot enforce this using a policy.

At any rate, why do you want to throw an exception when an exception class is loaded? Maybe you could explain your problem, then someone might be able to propose a solution.

Edit:

One way to prevent loading of certain classes would be to remove them from the JRE installation. Most system classes are contained in rt.jar in your JDK/JRE installation. You should be able to modify it with any ZIP-tool.

Just create a special installation of your JRE, and modify its rt.jar. That is an ugly hack, but should be OK for testing purposes...

sleske
+5  A: 

You could write a small loader application that creates a new, custom classloader. Your application classes could then be loaded using this classloader.

In the custom classloader, you can then throw ClassNotFoundException when your application tries to access a class that you want to blacklist.

You will need to overload the load() method. This method will be responsible for throwing the exception on your blacklisted classes ordelegating to the parent Classloader if the class is allowed. A sample implementation:

public Class loadClass(String name) throws ClassNotFoundException {
    if(name.equals("javax.lang.ClassIDontLike")){
       throw new ClassNotFoundException("I'm sorry, Dave. I'm afraid I can't do that.");
    }
    return super.loadClass(name, false);
}

(Of course, a real implementation can be way more sophisticated than this)

Because the classes of your application are loaded through this Classloader, and you are only delegating the loadClass() invokations to the parent classloader when you want to, you can blacklist any classes that you need.

I am pretty sure that this is the method that Google uses to blacklist classes in their server. They load every app in a specific Classloader. This is also similar to the way that Tomcat isolates the different Web Applications.

Mario Ortegón
I think Class.forName() may circumvent a custom classloader and go right to boot/system class loading. I think there are command line arguments to replace even the boot classloader, might want to look there too
basszero
You are right, Class.forName() would use the boot/system Classloader. This is a common source of grief when using Eclipse.
Mario Ortegón
+1  A: 

Wouldn't you rather get compilation errors than runtime errors while testing your program? You could configure your IDE or compiler to warn you when an undesired class is instantiated. I know AspectJ has some nice features for this: You can define compilation warnings/errors on join points and get feedback in e.g. Eclipse. To use this in Eclipse, you simply install the AspectJ plugin and write a suitable aspect. To get the errors while compiling from a command line or script, you would actually have to use the AspectJ compiler, but I doubt that you would need that.

Maarten Winkels