I have a jar in the servlet. This jar has a variable called 'projectDirecotry'. Logically, I want the 'projectDirectory' to hold different values for each user. Since the variable is made static, I face race condition here. I know it is a bad design to use static variables but I dont have any control over the source code of this jar. I found that the scope of the static variable is limited to the classloader. I'm just wondering if it is possible to create a different classloader to this jar for each user so that the static variable is no longer shared by the users.
Any member variable in a servlet is discouraged, because there typically will be only one servlet object ever. All of the state needs to go into the request/response objects, not in the servlet.
It sounds like you have to run buggy code, are not able/allowed to fix it, but still should make it work. The way to make it work is to fix the original code, not to muck with classloading mechanics or anything else.
Run!
If you don't, and somehow magically fix this issue: Where there is a fundamental bug of this class, there are more. In the end, you will be the one who is blamed for any future misfunction, because you built an absolute nonstandard infrastructure.
Imagine the next problem to be a performance problem. Or another member variable, XSS, CSRF. The probability is high, if you're now struggling with a static variable in a servlet.
Fix it at the root, or run away. Resist any second-class workaround, for any price.
Related
Let me explain,
Theirs a plugin (video game mod) I want to make to add things to Another plugin (a different mod) but I don't want to change anything in the plugin I'm not making. But to add the stuff I want, I'd have to add some variables to some arrays in a certain class, which I could totally do form another class but Their finalized, and all the spots are taken.
SO after looking into how final variables work (i kinda guessed) I though it might just be easier to
make a copy of the class in question, put it in my plugin, change the variables so their not final, and... OVERRIDE the original class when the program starts... some how.
Ok not easy, but that was the only thing that came to mind, where I still didn't edit the original files, and my plugin could be removed and added without changing anything.
I've looked into Classloaders and something someone called a patching assistant (it implements ClassFileTransformer) but I have no idea what I'm doing. SO I thought I'd post what I'm trying to do on here and see if anyone had any advice, I'll keep trying to figure out whether a class loader or patching assistant are viable for what I want in the mean time.
Thanks in advance!
You can do this with reflection:
http://java-performance.info/updating-final-and-static-final-fields/
Although it's probably not such a great idea - these fields are final for a reason.
I work in a pretty large Java-project (2500+ classes) that uses an old code standard where all
member variables are prefixed with "m_" (e.g m_temperature). There is really no reason for this any longer and I'd like to get rid of them but:
In order to make the change I must do all variables at once.
It must not generate any bugs.
The first naive approach of simply renaming all the "m_variable" to just "variable" will not be sufficient as that could produce name collisions between an already existing variable named "variable", and the newly renamed one.
So, to sum up:
How do I rename all these pesky member variablest without getting into trouble and are there any more problems than the one mentioned above?
Yes, I'm aware of the refactoring/renaming features within IDEs, please bear in mind that I want to do the changes to all variables matching the criteria at once and not by right-clicking on variables and renaming them one-by-one.
How about below from : mass renaming of java variables
by Simulant
click on the variable name.
1:press [alt] + [shift] + [R]
2:enter the new name.
3:press [enter] to confirm.
-->all instances of this variable will be renamed.
Theres a question on SC which is about a massive refactoring in java too. The best answer is using japvaparser and implementing a visitor to do the actual refactoring. This shouldn't be that much work for a simple rename.
To answer your second question (are there any more problems)
I would avoid global variables. Favour encapsulation such that you can localise functionality.
I would implement some unit tests such that you can verify future changes. At the moment it appears your only available check is that your project compiles properly.
I realise both of these are potentially sizable issues in an existing project. But it's worth lookingto identify possible pain points and work on those first of all.
Refactoring tool will help in this case. When you rename a variable, it will rename it in all dependent places including if it is called in different class file. While doing this, it will alert you in case if your renamed variable matches with already existing name.
However we have to do it manually for each variable.
I don't know if this can work.
But I find this link to find and replace all occurence in a project using IntelliJ.
http://www.jetbrains.com/idea/webhelp/finding-and-replacing-text-in-project.html
If you are using eclispe IDE, you can do it in easy manner.
Steps:
select the variable
right click on it
click on refactor
click on rename
even in netbeans you can follow same steps.
The IDE finds the reference and usages and replace it all.
I want to store debug variables while using a breakpoint and restore them regardless of the application. I probably need some plugin to let me serialize variables and restore them anytime.
To be more specific I want:
breakpoint
see variables, store them
let the flow go further
restore variables and view them in a convenient way (maybe in debug, but not while debugging) and compare variables with my application's view tier
ps. I was trying to find some plugin, but without results.
thanks
I completetly agree with stacker, to answer for your next question about expand all it's very hard to implement for eclipse guys - regarding to this
One risk is the difficulty of dealing
with self-referencing structures,
because application have to expand
them only one time. There may be
variable A which has a reference to B;
and there may be a variable B which
has a reference to A. This kind of
problems -seem- can easily solve by a
set, however this isn't the best
approach. Another risk may be the
quantity of the features I proposed. I
think it would be better to withdraw
some of these. I published them here,
because I couldn't determine which.
The only thing you can do (using the standard debugger) is, to copy the textual information from the variables view into the clipboard (Ctrl-C) and store (Ctrl-V) it in a texteditor for later reference. Please note that only expanded nodes, from the variables view, will be copied.
In my application I use some icons. Where should I store the path of the directory containing those icons ?
The icons are used in different classes so it doesn't really make sense to store them in one of those classes in particular.
I read that global variables are evil, but is it acceptable to use a class (eg Commons) containing only public static final fields to store this king of data ? What solution is used in professional applications ?
Global Constants
As others state, global constants don't have the same negative connotation as global variables. Global variables make a program difficult to debug and maintain because of uncontrolled modifications. Global constants (public static final) don't create the same problem
Nevertheless, object-orientation is about binding code close to its data to enhance understandability and maintainability. You still have to find the right balance between storing global configuration values in a global class vs keeping data close to the code that will use it.
It is probably also worth reminding here that, because the compiler may inline some constants, if you change a constant value, you may have to recompile and redeploy more than just the class that contains the constants.
Externalizing Values
You also asked about what professional apps do. Its not uncommon for those apps to make these types of values, like files paths, externally configurable. It depends on how likely the value is to change (i.e. how likely your app will move or your code will be used in another app) and how convenient or easy it is to recompile and redeploy the code with new values. If you do choose to make some values externally configurable, you still may want to encode default values for those items in the code.
Here are some ways to externalize those values and some links to get you started. This is of course not an exhaustive list:
System properties so you can specify them on the command line
Property files [See StackOverflow Q - How to use java property files?]
Resource Bundles [See StackOverflow Q - How to load a resource bundle from a file resource?]
Global variables are evil (since they make it nearly impossible to figure out who modifies what), but constants aren't evil. public static final String fields are fine, since they can't be modified.
I would recommend to include them (the icons) with your class files in a jar, say a folder called resources and only the icon loader needs to know the resources folders name within your jar.
You are referring to constants, not global variables, so don't worry about them being evil - they are not, because they don't change.
if they are used by one class - place them in that class
if they are used by multiple classes in one package - place them in a special class
if they are used by multiple classes and they logically belong somewhere, place them there.
Have in mind that in case these "constants" are actually configurable, you'd better pass a Configuration object to methods that need it. Well, you may have the static somewhere, but from testability point of view it is a must to inject them / pass them.
Global variables are not the same as global constants. The reason global variables are bad is because they can be changed anywhere in the code and it is very hard to track down errors that result from a global variable not being in the expected state. Global constants will always be in their expected state because they can never be changed inadvertently.
In general I would suggest that this particular case be a packaging problem and to not reference the items as files on the file system, but rather as elements in the classpath, and load them via a classloader. This requires setting their location in the classpath of your application.
Then there should only be one class that knows how to retrieve these icons, and all other code asks that class for the icons it needs.
My problem is that I'm working on a project that requires me to run multiple instances of someone elses code which has many static attributes/variables, which causes all the instances to share those resources and, well, crash. I can run multiple instances of this other person's program if I create a .jar file off of it and open it multiple times by running the .jar in windows, but running calling the "main" method multiple times in my code (which is what I need to do) won't work.
I thought about creating a .jar and using Runtime.getRuntime().exec( "myprog.jar" ); to call the program multiple times, but that won't work for me since I have to pass an instance of my object to this new program and I don't think this solution would allow for that.
PS: This is also posted in the Sun forums, so I`ll post the answer I get there here or the answer I get here there naturally giving proper credit once I this is solved =P.
Remember that a static element in Java is unique only in the context of a classloader (hierarchy); a class is uniquely identified in a JVM by the tuple {classloader, classname}.
You need to instantiate isolated classloaders and load the jar using that class loader. Each loaded class (and thus statis elements) are unique in their classloader and will not interfere with one another.
I'd say you have three alternatives:
Refactor the legacy application so that it doesn't use static attributes. If you can do this, this may be the best solution in the long term.
Continue with your approach of launching the legacy application in a separate JVM. There are a number of ways that you can pass (copies of) objects to another JVM. For example, you could serialize them and pass them via the child processes input stream. Or you could stringify them and pass them as arguments. In either case, you'll need to create your own 'main' class/method that deals with the object passing before calling the legacy app.
I think you should be able to use classloader magic to dynamically load a fresh copy of the legacy application each time you run it. If you create a new classloader each time, you should get a fresh copy of the legacy application classes with a separate set of statics. But, you have to make sure that the legacy app is not on your main classpath. The problem with this approach is that it is expensive, and you are likely to create memory leaks.
The description is a little confusing.
If you are running the code multiple times, you are running multiple independent processes, each running in its own JVM. There is no way that they are actually sharing the values of their static fields. Java doesn't let you directly share memory between multiple VMs.
Can you elaborate more (ideally with examples and code) what the attributes are defined as and what kind of failures you are getting? This may be completely unrelated to them being static.
In particular, what exactly do you mean by shared resources? What resources are your programs sharing?
The proper approach was already suggested - using custom ClassLoaders. Another thing comes to my mind, which might seem ugly, but will probably do, and is a bit more object-oriented approach.
The legacy code is used for its operations, and it incorrectly uses static instead of instance variables. You can fix that using inheritance and reflection:
create (or reuse) an utility class that copies instance variables to static ones
extend the classes in question and provide the same instance variables as the static ones
override all methods. In the overriding methods use the utility to copy the state of the current object to the static variables, and then delegate to (call) the super methods.
Then start using instance of your class, instead of the legacy ones. That way you will simulate the proper behaviour.
Have in mind this is NOT thread-safe.