After some help in an other thread on urlclassloaders - understanding urlclassloader, how to access a loaded jar's classes
I have a follow on question as I don't think I am approaching the problem correctly.
myPackageA.start has a urlclassloader calling myPackageB.comms
myPackageB.comms has an dependency to import org.jgroups.JChannel
form /home/myJars/jgroups-3.4.2.Final.jar with the following code
package myPackageB;
import org.jgroups.JChannel;
public class SimpleChat {
JChannel channel;
String user_name=System.getProperty("user.name", "n/a");
private void start() throws Exception {
channel=new JChannel();
channel.connect("ChatCluster");
channel.getState(null, 10000);
channel.close();
}
public static void main(String[] args) throws Exception {
new SimpleChat().start();
}
}
normally I would call the above code with java -cp /home/myJars/jgroups-3.4.2.Final.jar:myPackageB myPackageB.SimpleChat and runs as expected.
My question is howit possible to set the -cp within the script so the import works when using the below code to call myPackageB.SimpleChat from java -cp myPackageA.jar myPackageA.start
package myPackageA;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class start
{
Class<?> clazz;
private void start() throws Exception
{
if (this.clazz == null)
throw new Exception("The class was not loaded properly");
Object mySc = this.clazz.newInstance();
Method sC = this.clazz.getDeclaredMethod("main", String[].class);
String[] params = null;
sC.invoke(mySc, (Object) params);
}
public void loadSc() throws Exception
{
URL classUrl;
classUrl = new URL("file:///home/myJars/myPackageB.jar");
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
Class<?> c = ucl.loadClass("myPackageB.SimpleChat");
this.clazz = c;
}
public static void main(String[] args) throws Exception
{
start startnow = new start();
startnow.loadSc();
startnow.start();
}
}
thanks
Art
Just add the URL for jgroups-3.4.2.Final.jar to the URLClassLoader's array of URLs.
Related
i have problems with matlabcontrol liblary especially using eval and feval function.
this is my program
package matlab;
import java.io.IOException;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.extensions.MatlabNumericArray;
import matlabcontrol.extensions.MatlabTypeConverter;
public class Matlab {
public static void main(String[] args) {
String address = "D:\\database.mat";
int hidden = 10;
int epoch = 100;
int mu = 1;
int lr =1;
int fail =1;
try {
MatlabProxyFactory factory = new MatlabProxyFactory();
MatlabProxy proxy = factory.getProxy();
proxy.eval("load"+address);
//there is problem here unclosed string literal
proxy.eval("net=newff(input,target,["+hidden+"),(logsig, tansig),trainlm);
proxy.eval("net.trainparam.showwindow=true;");
proxy.eval("net.divideRand='trainlm';");
proxy.eval("net.trainparam.epochs="+epoch+";");
proxy.eval("net.trainparam.mu="+mu+";");
proxy.eval("net.trainparam.lr="+lr+";");
proxy.eval("net.trainparam.goal=0;");
proxy.eval("net.trainparam.max_fail="+fail+";");
proxy.eval("net=train(net,input,target);");
proxy.eval("class_Matlab=sim(net,target);");
proxy.eval("save net net class_Matlab");
proxy.disconnect();
} catch (MatlabConnectionException ex) {
Logger.getLogger(Matlab.class.getName()).log(Level.SEVERE, null, ex);
} catch (MatlabInvocationException ex) {
Logger.getLogger(Matlab.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
i still dont know how to use eval and feval properly, can someone explain me how to use eval and feval?
i tested the library using example from mathworks and it worked fine
package matlab;
import java.io.IOException;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.extensions.MatlabNumericArray;
import matlabcontrol.extensions.MatlabTypeConverter;
public class Matlab {
public static void main(String[] args) {
try {
MatlabProxyFactory factory = new MatlabProxyFactory();
MatlabProxy proxy = factory.getProxy();
proxy.eval("[x,t] = simplefit_dataset;");
proxy.eval("net= feedforwardnet(10);");
proxy.eval("net = train(net,x,t);");
proxy.eval("view(net)");
proxy.disconnect();
} catch (MatlabConnectionException ex) {
Logger.getLogger(Matlab.class.getName()).log(Level.SEVERE, null, ex);
} catch (MatlabInvocationException ex) {
Logger.getLogger(Matlab.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String[] args) throws MatlabConnectionException, MatlabInvocationException
{
MatlabProxyFactoryOptions options =
new MatlabProxyFactoryOptions.Builder()
.setUsePreviouslyControlledSession(true)
.build();
MatlabProxyFactory factory = new MatlabProxyFactory(options);
MatlabProxy proxy = factory.getProxy();
proxy.feval("matlab_filename");
proxy.disconnect();
}
and
public static void main(String[] args) throws MatlabConnectionException, MatlabInvocationException { //Create a proxy, which we will use to control MATLAB MatlabProxyFactory factory = new MatlabProxyFactory(); MatlabProxy proxy = factory.getProxy();
//Set a variable, add to it, retrieve it, and print the result
proxy.setVariable("a", 5);
proxy.eval("a = a + 6");
Object result = proxy.getVariable("a");
System.out.println("Result: " + result);
//Disconnect the proxy from MATLAB
proxy.disconnect();
}
and
Public static void main(String[] args) throws MatlabConnectionException, MatlabInvocationException { //Create a proxy, which we will use to control MATLAB MatlabProxyFactory factory = new MatlabProxyFactory(); MatlabProxy proxy = factory.getProxy();
//Display 'hello world' like before, but this time using feval
proxy.feval("disp", "hello world");
//Disconnect the proxy from MATLAB
proxy.disconnect();
}
For more help, please execute the examples first. https://code.google.com/archive/p/matlabcontrol/wikis/Walkthrough.wiki
Hope it will help you.
I export my own project into a jar, and this project needs two 3rd-party jars, an extra TestMyJar.class is used to test my project, how to do this? I have tried several methods but no luck. To be more specific, this is my jar: a class that only delivers hello world message a url. I export this class code into a helloworld.jar
package com.wow.flow.http.dq;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
public class HttpConnection {
#SuppressWarnings("deprecation")
public void client() throws Exception {
String url = "www.someurl.com"; // sorry if this your registered url, just borrow it as an example
if (url == null) {
throw new Exception();
}
HttpClient client = new HttpClient();
PostMethod postMethod = new UTF8PostMethod(url);
try {
postMethod.setRequestBody("Hello world");
int statusCode = client.executeMethod(postMethod);
if (statusCode == HttpStatus.SC_OK) {
InputStream responseBody = postMethod.getResponseBodyAsStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(responseBody, "utf-8"));
String line = reader.readLine();
while (line != null) {
System.out.println(new String(line.getBytes()));
line = reader.readLine();
}
}
} catch (HttpException e) {
// TODO: handle exception
} catch (IOException e) {
// TODO: handle exception
} finally {
postMethod.releaseConnection();
}
}
// Inner class for UTF-8 support
public static class UTF8PostMethod extends PostMethod {
public UTF8PostMethod(String url) {
super(url);
}
#Override
public String getRequestCharSet() {
// return super.getRequestCharSet();
return "UTF-8";
}
}
}
It requires dom4j and httpclient. This is my TestMyJar.class:
package httptest
public class TestMyJar {
public static void main(String[] args) {
HttpConnection connection= new HttpConnection();
}
}
Now I have three jar: helloworld.jar, commons-httpclient-3.1.jar, dom4j-1.6.1.jar, and a class: TestMyJar.java. How can I compile and run TestMyJar.java? I have tried with javac and java, but it is all something cannot be found.
Thanks!
you can include as many jars as you wish with the command
javac MyClass.java -cp jar1 jar2 jar3
java -cp jar1 jar2 jar3 MyClass
On Windows, you could just run your main class with command like:
java c:/lib/helloworld.jar;c:/lib/commons-httpclient-3.1.jar;c:/lib/dom4j-1.6.1.jar httptest.TestMyJar
While on Linux, use:
java /lib/helloworld.jar:/lib/commons-httpclient-3.1.jar;/lib/dom4j-1.6.1.jar httptest.TestMyJar
Where httptest is your package name and TestMyJar is your class with main method in it.
This question already has answers here:
Why do I get a ClassNotFoundException when using Class.forName(...)?
(2 answers)
Closed 8 years ago.
I have used JavaCompiler to compile a class that I generate on the fly. The compile task succeeds. I then try to load the compiled class using Class.forName("MyClass"); and it fails with a ClassNotFoundException. Is there a known issue with doing this?
package com.amir.method;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.tools.*;
public class MethodGenerator {
private final static MethodGenerator INSTANCE = new MethodGenerator();
private MethodGenerator() {
}
public static MethodGenerator get() {
return INSTANCE;
}
public static void main(String[] args) {
final Class<?> clz = MethodGenerator.get().compile("Foo", "doIt"); //<- args ignored for now
}
public Class compile(final String className,
final String methodName) {
try {
return doCompile(className, methodName);
} catch(final Exception e) {
throw new RuntimeException(this.toString(), e);
}
}
private Class doCompile(final String className,
final String methodName) throws IOException, ClassNotFoundException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class HelloWorld {");
out.println(" public static void main(String args[]) {");
out.println(" System.out.println(\"This is in another java file\");");
out.println(" }");
out.println("}");
out.close();
final JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());
final Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
final String classPath = System.getProperty("java.class.path") + File.pathSeparator;
final String bootClassPath = System.getProperty("sun.boot.class.path") + File.pathSeparator;
final List<String> options = new ArrayList<String>();
options.add("-classpath");
final StringBuilder builder = new StringBuilder();
builder.append(classPath);
builder.append(bootClassPath);
final URLClassLoader urlClassLoader = (URLClassLoader) ClassLoaderResolver.getClassLoader();
for (final URL url : urlClassLoader.getURLs()) {
builder.append(url.getFile()).append(File.pathSeparator);
}
final int lastIndexOfColon = builder.lastIndexOf(File.pathSeparator);
builder.replace(lastIndexOfColon, lastIndexOfColon + 1, "");
options.add(builder.toString());
final JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, options, null, compilationUnits);
boolean success = task.call();
if(success) {
final Class<?> cls = Class.forName("HelloWorld", true, urlClassLoader);
return cls;
}
return null;
}
class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}
Try to load the class after compiling it by using, Thread.currentThread().getContextClassLoader().loadClass("com.ur.class");
Found this...check if this can help..
// Create a new custom class loader, pointing to the directory that contains the compiled
// classes, this should point to the top of the package structure!
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()});
// Load the class from the classloader by name....
Class<?> loadedClass = classLoader.loadClass("com.ur.class");
// Create a new instance...
Object obj = loadedClass.newInstance();
// Santity check
if (obj instanceof com.ur.class) {
// code here ...
}
For more information refer this: How do you dynamically compile and load external java classes?
I am trying to develop a script in Java which finds all .jar files in a specified directory, then them to classpath and under certain conditions, invokes their main() method. Here is my Java info:
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.5) (6b24-1.11.5-0ubuntu1~12.04.1)
OpenJDK Server VM (build 20.0-b12, mixed mode)
Here is the ls of the current working dir:
clojure.jar
loader.class
loader.java
I am doing the following in order to add clojure.jar to the classpath and invoke its main method:
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.lang.reflect.Method;
public final class loader {
public static void main (String[] args) {
try {
printClasspathString();
System.out.println ("**********");
URL[] classesRepo = { new File("clojure.jar").toURI ().toURL (),
new File(System.getProperty("user.dir")).toURI ().toURL ()};
ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
URLClassLoader urlClassLoader = new URLClassLoader( classesRepo, currentThreadClassLoader);
Thread.currentThread().setContextClassLoader(urlClassLoader);
printClasspathString();
} catch (Exception ex) {
System.out.println(ex.getMessage ());
}
//Do I miss something here?
String mainClassName="clojure.main";
Class<?> mainClass = null;
try {
mainClass = Class.forName(mainClassName);
}
catch (Exception ex) {
throw new IllegalArgumentException("class not found in your jar file " + mainClassName);
}
Method mainMethod = null;
try {
mainMethod = mainClass.getMethod("main", String[].class);
}
catch (Exception ex) {
throw new IllegalArgumentException("class to launch (" + mainClassName + ") does not have a public static void main(String[]) method");
}
try {
mainMethod.invoke(null, (Object) args);
} catch (Exception ex) {
System.out.println(ex.getMessage ());
}
}
public static void printClasspathString() {
ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader();
if (applicationClassLoader == null) {
applicationClassLoader = ClassLoader.getSystemClassLoader();
}
URL[] urls = ((URLClassLoader)applicationClassLoader).getURLs();
for(int i=0; i < urls.length; i++) {
System.out.println (urls[i].getFile());
}
}
}
Unfortunately, the loader doesn't work as expected:
$ java -cp . loader
/home/proofit404/data/downloads/clojure-loader/
**********
/home/proofit404/data/downloads/clojure-loader/clojure.jar
/home/proofit404/data/downloads/clojure-loader/
Exception in thread "main" java.lang.IllegalArgumentException: class not found in your jar file clojure.main
at loader.main(loader.java:37)
If I use the -cp option, though, everything works fine:
$ java -cp .:clojure.jar loader
/home/proofit404/data/downloads/clojure-loader/
/home/proofit404/data/downloads/clojure-loader/clojure.jar
**********
/home/proofit404/data/downloads/clojure-loader/clojure.jar
/home/proofit404/data/downloads/clojure-loader/
Clojure 1.4.0
user=> (System/exit 0)
So - what is it that I need to change in my code to make it work as expected?
I think the problem is that the Class.forName(String) method does not use the threads contextclassloader, but the classloader of the current class:
public static Class<?> forName(String className)
throws ClassNotFoundException
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
This means your URLClassLoader wont be used. Try instead to explicitly pass the classloader by using Class.forName(String,boolean, ClassLoader):
mainClass = Class.forName(mainClassName, true, urlClassLoader);
Try this code and follow the comments given below:
import java.net.URL;
import java.io.IOException;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
public class JarLoader extends URLClassLoader {
public JarLoader(URL[] urls) {
super(urls);
}
public void addFile(String path) throws MalformedURLException {
String urlPath = "jar:file://" + path + "!/";
addURL(new URL(urlPath));
}
public static void main(String args[]) {
try {
System.out.println("First attempt...");
Class.forName("org.gjt.mm.mysql.Driver");
//specify your class name above
} catch (Exception ex) {
System.out.println("Failed.");
}
try {
URL urls[] = {};
JarLoader cl = new JarLoader(urls);
cl
.addFile("/opt/mysql-connector-java-5.0.4/mysql-connector-java-5.0.4-bin.jar");
// give your jar file above.
System.out.println("Second attempt...");
cl.loadClass("org.gjt.mm.mysql.Driver");
//specify your class name above
System.out.println("Success!");
} catch (Exception ex) {
System.out.println("Failed.");
ex.printStackTrace();
}
}
}
I am thinking using truezip API in Java to manipulate with ear file by
extract ear into tmp directory,
then search through jars in tmp,
if found properties in jar,
then extract it into tmp,
modify that property
then pack it back into jar,
then pack jar back into ear.
OR is there a better way in using shell script?
Please advise.
Thanks
Using TrueZIP 7, you could use something like this:
public static void main(String args[]) throws IOException {
// Remember to add the following dependencies to the class path:
// Compile time artifactId(s): truezip-file
// Run time artifactId(s): truezip-kernel, truezip-driver-file, truezip-driver-zip
TFile.setDefaultArchiveDetector(new TDefaultArchiveDetector("ear|jar|war"));
search(new TFile(args[0])); // e.g. "my.ear"
TFile.umount(); // commit changes
}
private void search(TFile entry) throws IOException {
if (entry.isDirectory()) {
for (TFile member : dir.listFiles())
search(member);
} else if (entry.isFile()) {
if (entry.getName().endsWith(".properties");
update(entry);
} // else is special file or non-existent
}
private void update(TFile file) throws IOException {
Properties properties = new Properties();
InputStream in = new TFileInputStream(file);
try {
properties.load(in);
} finally {
in.close();
}
// [your updates here]
OutputStream out = new TFileOutputStream(file);
try {
properties.store(out, "updated");
} finally {
out.close();
}
}
I used the answer from #Christian Schlichtherle to get me started on what I was trying to accomplish, but the usage of True Zip has changed quite a bit. I thought I'd post what I needed to do here to hopefully help someone.
You need to create a class that extends TApplication. In my case I'm making it abstract so I can reuse the setup code in my implementing logic classes.
Application.java:
import de.schlichtherle.truezip.file.TApplication;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TConfig;
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
/**
* An abstract class which configures the TrueZIP Path module.
*/
abstract class Application<E extends Exception> extends TApplication<E> {
/**
* Runs the setup phase.
* <p>
* This method is {#link #run run} only once at the start of the life
* cycle.
*/
#Override
protected void setup() {
TConfig.get().setArchiveDetector(
new TArchiveDetector(
TArchiveDetector.NULL,
new Object[][] {
{ "zip", new ZipDriver(IOPoolLocator.SINGLETON)},
{ "ear|jar|war", new JarDriver(IOPoolLocator.SINGLETON)},
}));
}
}
Then you just extend the abstract class and implement the "work" method as shown.
ChangeProperty.java:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.ServiceConfigurationError;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import de.schlichtherle.truezip.file.TFileOutputStream;
public class ChangeProperty extends Application<IOException> {
public static void main(String args[]) throws IOException {
try {
System.exit(new ChangeProperty().run(args));
} catch (ServiceConfigurationError e) {
// Ignore this error because what we wanted to accomplish has been done.
}
}
private void search(TFile entry) throws IOException {
System.out.println("Scanning: " + entry);
if (entry.isDirectory()) {
for (TFile member : entry.listFiles())
search(member);
} else if (entry.isFile()) {
if (entry.getName().endsWith(".properties")) {
update(entry);
}
}
}
private void update(TFile file) throws IOException {
System.out.println("Updating: " + file);
Properties properties = new Properties();
InputStream in = new TFileInputStream(file);
try {
properties.load(in);
} finally {
in.close();
}
// [your updates here]
// For example: properties.setProperty(key, newValue);
OutputStream out = new TFileOutputStream(file);
try {
properties.store(out, "updated by loggerlevelchanger");
} finally {
out.close();
}
}
#Override
protected int work(String[] args) throws IOException {
search(new TFile(args[0]));
return 0;
}
}