I have some misterious problem with system proxy detection:
Actually, I have the right code to detect system proxy settings at runtime, it can handle pac files and http proxy settings as well.
It works absolutely correct, when I store and execute everything on the target station.
BUT: I run one little piece of code on the target station and store anything else (jars) on another station, on which apache webserver runs. From the main I load the classes with URLClassloader, so that piece of code loaded via network, which responsible for the proxy detection as well. And in this way the default proxy selector give DIRECT all time, it is not able to find the right settings.
I think, the problem is that I want to set the
System.setProperty("java.net.useSystemProxies","true");
In the loaded class and somehow this does not work...But when I sysout the property value, it is true.
I wrote a little test program and the only difference is that:
A)
Class.forname("a"); -> a is in the classpath
B)
URL[] url = new URL[1];
url[0] = new URL("http://1.2.3.4/dtfw");
URLClassloader u = new URLClassloader(url);
Class.forname("a", true, u);
Both piece of code work, the only different is in the output.
Does anyone have some idea?
Thanks in advance!!
Zsomi
I found the root cause of the problem:
The DefaultProxySelector is singleton per JVM and the behavior of it based on if System.setProperty("java.net.useSystemProxies","true"); is set or not.
As the URLClassloader uses it, this value is false, when it is instantiated. And when in the "a" class I try to use it, it is not able to find system proxy settings, since at instatiation this property was not set.
So I have the cause, but no solution yet.
Regards,
Zsomi
Related
In a Tomcat 7 I have a pretty standar jar file on WEB-INF/lib. Inside this jar I have this class called Parser, and next to it (on the same dir) I have another one called AutomaticLocalLoader. Compilation gives no problem at all. In run time the AutomaticLoader class is found, and when It needs the Parser class, I get a NoClassDefFoundError
The Parser and AutomaticLoader class have been working without this problem for 15 years!! in many diferent vers of java and tomact; and now out of the blue, I am getting this NoClassDefFoundError, only for the Parser class. I already put a copy on a directory inside the WEB-INF/classes path and still got the same error. I already created my own ClassLoader to see if I get some error loading the class from the WEB-INF/classes directory by myself, but I can load it without problems.
log.info("Leer " + aFlInstructions[i].getAbsolutePath());
LoaderTest A = new LoaderTest();
A.test("com.hds.resolve.model.aguila.AutomaticLocalLoader");
LoaderTest B = new LoaderTest();
B.test("com.hds.resolve.model.aguila.Parser");
if(!bOverrideInputDir)
Psr = new Parser(aFlInstructions[i]);
else
Psr = new Parser(aFlInstructions[i], new String[] { StrLocalDirectory } );
The LoaderTest class, try to create the Class Object for the given name using Class.forName. If NoClassDefFoundError, then try to load the class using my own classloader and then create the class.
For the AutomaticLoader, it succed at the first try. For the Parser class if fails, then successfully load it with the custom classloader. Of course when the code reach the "new Parser" part, the old webclassloader still fails and throws the NoClassDefFoundError.
Both Parser and AutomaticLocalLoader belong to the same package and are stored on the same jar inside WEB-LIB.
Funny enough, the error does always happen on production... but never in my machine. I do not use customs classloaders except for doing this debug. Also, trying an old version of the software seems to fix the error. No idea why.
I think I can hack a solution messing with the tomcat's webclassloader, but I really would prefer to understand what is going wrong with this code.
I want to change the logging level depending if I'm debbugging or not, but I can't find a code snippet to check if the application is running in debug mode.
I'm using eclipse to debug the application, so if the solution only works within Eclipse it will be fine.
Found the answer on how-to-find-out-if-debug-mode-is-enabled
boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean().
getInputArguments().toString().contains("-agentlib:jdwp");
This will check if the Java Debug Wire Protocol agent is used.
You could modify the Debug Configuration. For example add a special VM argument only in the Debug Configuration. You can use System.getProperties() to read the supplied arguments.
Even better, modify the configurations (Run and Debug) to load a different logging configuration file. It isn't good if you need to write code to determine the logging level. This should only be a matter of configuration.
There is not an officially sanctioned way to reliably determine if any given JVM is in debug mode from inside the JVM itself, and relying on artifacts will just break your code some time in the future.
You will therefore need to introduce a methology yourself. Suggestions:
A system property.
An environment variable (shell variable like $HOME or %HOME%)
Ask the JVM about the physical location of a given resource - http://www.exampledepot.com/egs/java.lang/ClassOrigin.html - and based on it, make your decision (does the path contain the word "debug"? is it inside a jar or an unpacked class file? etc).
JNDI
The existance or content of a particular resource.
Have you tried add a vm argument in the eclipse run config?
Pass this as a VM Argument
-Ddebug=true
then you can do Boolean.getBoolean("debug") to check this.
If you are setting the debug level from your own program, may be a line like:
public static final boolean DEBUG_MODE = System.getProperty("java.vm.info", "").contains("sharing");
would do the trick.
Just tested it in eclipse3.5:
package test;
public class Test
{
/**
* #param args
*/
public static void main(String[] args)
{
System.out.println(System.getProperty("java.vm.info", ""));
}
}
will display:
mixed mode, sharing
if launched without debug
mixed mode
if executed with debug launcher
Joachim Sauer comments:
This is highly system depending.
I assume the "sharing" indicates that cross-VM class-sharing is active.
This is a very new feature and is only available on some platforms.
Furthermore there can be many possible reasons to en- or disable it, so I wouldn't use this for debug-mode detection.
(Note: I tested it with the latest jdk1.6b14. I leave this as a CW answer.)
Have a look here:
http://wiki.eclipse.org/FAQ_How_do_I_use_the_platform_debug_tracing_facility%3F
Moreover, I think you can't know if your app is run in debug mode. The only thing you can do is to pass an argument to your JVM when you debug.
Manu
If using socket (e.g. 9999) you can call netstat to check if connection was established:
Process p = new ProcessBuilder("netstat", "-n").start();
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
Then scan in stdout for 127.0.0.1:9999.*ESTABLISHED
I want to know whether the user launched our Java-based application from a read-only file system like from a .dmg, so functions like auto-update will be able to show meaningful information instead of aborting with an error. I first thought checking the .app's path would be sufficient (when launched from a .dmg it is something like /Volumes/MyApp 1.2.3/MyApp.app, but this won't work, because the user might have installed the application on a different partition. What other things may I check?
You can use -[NSURL getResourceValue:forKey:error:] with the key NSURLVolumeIsReadOnlyKey. You would apply this to the app bundle URL as returned by [[NSBundle mainBundle] bundleURL]. So:
NSBundle* bundle = [NSBundle mainBundle];
NSURL* bundleURL = bundle.bundleURL;
NSNumber* readOnly;
NSError* error;
if ([bundleURL getResourceValue:&readOnly forKey:NSURLVolumeIsReadOnlyKey error:&error])
{
BOOL isReadOnly = [readOnly boolValue];
// act on isReadOnly value
}
else
{
// Handle error
}
If OSX is POSIX compliant, to determine if filesystem is mounted R/O, You can use statvfs() or fstatvfs(), returned struct statvfs field f_flag should have ST_RDONLY bit set for R/O filesystem.
As it was pointed in comments, check if this information is correctly provided by OS.
JNA and this question may be usefull for Java.
A few more ideas, which may be usefull here (access(), open(), utime() ).
OS X specific statfs() may be used too, but this function is not portable (Linux and *BSD have slightly different statfs() functions).
You can also check directly from Java whether a certain path points to something within a read-only directory by querying the FileStore associated with your path:
File classpathRoot = new File(MyClass.class.getClassLoader().getResource("").getPath());
/* getPath() actually returns a String instead of a Path object,
* so we need to take this little detour */
Path yourAppPath = classpathRoot.toPath();
boolean isReadOnly = Files.getFileStore(yourAppPath).isReadOnly();
Here's my setup:
My server waits for IPlugin-Objects with an ObjectInputStream. The incoming IPlugin-Object is of an unknown class, so first, the class-file is transmitted and loaded by the classloader of the OIS. Then, the IPlugin itself is sent by the client. The cast of the IPlugin seems not to be a problem (when using my own classloader in the OIS). But the IPlugin uses jama and now I got an NoClassDefFoundException when I receive the object. The weird thing for me is, that in the servers classpath the Jama-library is contained. I also tried, to write a dummy-line, so the library will really be imported (and not ignored by the compiler).
Can anybody help me on that? It really bugs me...
Okay, I've got it:
The problem was, that my personal URIClassLoader got every URI possible, except the current classloader. Now the constructor looks like the following:
URLClassLoader loader = new URLClassLoader(new URL[]{pluginFolder.toURI().toURL()},
this.getClass().getClassLoader());
I created my own new R library (called "Media"). There is no problem when I try to load it with RGui, and I can call the functions defined in the new package. This is how I load it:
> library(Media)
But, I'm also trying to call that functions from Java/JRI code, and when I load the new R package, Java doesn't seem to find the pacakge, throwing the message "Error in library(Media) : object 'Media' not found"
This is my current code using JRI:
REXP rexpSetFolder = re.eval("setwd('C:/Users/Albert/Documents')");
REXP rexpFolder = re.eval("getwd()");
System.out.println(rexpFolder.asString());
REXP rexpLoad = re.eval("library(Media)"); // fails
It also fails without the 'setwd' command, and simple calls to existing R functions work fine. I'm using R 2.10 and the latest JRI 0.5-0 under Windows.
Any help would be appreciated.
Thank you very much.
Edit:
The parameter lib.loc seems to work, at least this sentence does not return an error:
library("Media", lib.loc = "c:/Users/Albert/Documents")
But after that, calling a function in the package with re.eval("myfunction()"); still fails, as the function is not properly found.
You can modify the library path - see ?.libPaths in R, you simply want to add your private library to the path. The GUI does that for you, but if you are outside it doesn't happen. For example:
re.eval(".libPaths('c:/users/foo/Documents/R')");
Then load your package.
Did you install the library properly first? You might want to try using the lib.loc parameter.
library("Media", lib.loc = "c:/Users/Albert/Documents")
My work-around was to copy the package from my personal library (%USERPROFILE%\Documents\R) to the global library (%R_HOME%\library).
It's not the best because this requires Administrator privileges which not all users will have...