Weka - Can't find a permissible class - java

I'm integrating Weka into a plug-in I'm writing for another application. I included weka.jar in my class path and for the most part, things seem to be working well. Unfortunately, when I get to the point of changing the options for some classifiers, I run into problems specific to being unable to find certain classes. For example, when I try to change the name of the classifier in the AdaBoost options, I get an error that ends like so:
java.lang.Exception: Can't find a permissible class called: weka.classifiers.bayes.BayesNet
Model options set to: -P 50 -S 1 -I 10 -W weka.classifiers.bayes.BayesNet
at weka.core.ResourceUtils.forName(ResourceUtils.java:84)
at weka.core.Utils.forName(Utils.java:1080)
at weka.classifiers.AbstractClassifier.forName(AbstractClassifier.java:91)
at weka.classifiers.SingleClassifierEnhancer.setOptions(SingleClassifierEnhancer.java:108)
at weka.classifiers.IteratedSingleClassifierEnhancer.setOptions(IteratedSingleClassifierEnhancer.java:115)
at weka.classifiers.RandomizableIteratedSingleClassifierEnhancer.setOptions(RandomizableIteratedSingleClassifierEnhancer.java:93)
at weka.classifiers.meta.AdaBoostM1.setOptions(AdaBoostM1.java:375)
I'm thinking that this might have something to do with me using the JAR in an OSGi bundle, but I'm not sure. Any ideas? Other than this issue, I'm able to train these classifiers just fine using the default options for them.
Thanks.

Solve this problem via set all parameters via setters.
This problem when you use like this
BayesNet processes = new BayesNet();
String options = "-D -Q weka.classifiers.bayes.net.search.local.K2 -- -P 1 -S BAYES -E weka.classifiers.bayes.net.estimate.SimpleEstimator -- -A 0.5";
processes.setOptions(weka.core.Utils.splitOptions(options));
Change set all param like this.(Here not all option, small example)
BayesNet processes = new BayesNet();
SimpleEstimator newBayesNetEstimator = new SimpleEstimator();
newBayesNetEstimator.setAlpha(0.5);
processes.setEstimator(newBayesNetEstimator);

Related

How to check if a class is loaded or not in a Java process

My task is to find out how many springboot app are running on a Linux system.
So What I am planning to do is,
1. to get all the java process IDs
$ ps -aux|grep java
2. Then somehow get the loaded classes from the IDs.
I don't know if it is possible or not. Someone please kind enough to guide me to the right direction?
P.S. : I am using java to run the above command by the help of Process class, something like this :
Process process = Runtime.getRuntime().exec("ps -ef");
So I want to do it from a java project.
I came to this page searching for a recipe "how to find if a jar has been loaded" (which is a bit different than the original question). But perhaps it will be useful for somebody:
I found jcmd as best way to get this info, for example:
I have a running JVM with PID 1 (it's a CN application started in K8s):
$ jps
1 MyAppLauncher
529 Jps
Figure out what options jcmd provides for this JVM:
[eceuser#ecs1-0 temp]$ jcmd 1 help
1:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help
With a bit of try and error, I found that VM.dynlibs does what I needed:
$ jcmd 1 VM.dynlibs | grep custom
7f59a4b3b000-7f59a4b3d000 r--s 00000000 fd:00 1116085962 /home/app/lib/custom-fi-extensions-0.0.1-SNAPSHOT.jar
So yes, this jar has been loaded.
You need to put some sort of identifier into your app's startup command line. E.g. something like:
String id = "com.app.demo";
When you run your app, make sure to include the string. Let's say you start it from within Java, do the following:
Runtime.getRuntime().exec("C:\...\javaw.exe -cp ... -Dwhatever=" + id + " com.app.app.demo.Main");
Get the application by id like $ps aux | grep -i com.app.app.demo. In Java call Runtime.getRuntime().exec("ps aux | grep -i com.app.app.demo");
I would prefer using ProcessBuilder instead(from Java 8), and running your command via bash:
Process process = new ProcessBuilder().command("bash", "ps aux | grep com.app.app.demo").start()
Hope this gives an idea.
Quick and dirty method: some static block into your class and in it print something into a log (or system.out). Static block is executed when class is loaded by class loader and not when the first instance instantiated (this is when constructor is called for the first time). Then if your printout is in the log then the class has been loaded. Example:
public class Sample {
private static final Logger logger = ...
static {
logger.info("class Sample is loaded");
}
...
}
Assuming you can identify some specific class which determines if the application is a springboot application, you could use some tool from the jdk, which can output loaded classes. I've tried it with jcmd(you'll find it under jre/bin/):
I'm not very good with bash so it might be not very efficient, but this works for me assuming that every springboot application has loaded class org.springframework.boot.logging.LoggingInitializationContext and no non-springboot app loads it.
ps aux | grep [j]ava | awk '{print $2}' | xargs -I{} jcmd {} VM.class_hierarchy | grep "org.springframework.boot.logging.LoggingInitializationContext"
It finds processes containing java, takes only the PID, passes it to the jcmd where you grep for the specific class. The output seems to be correct, the only problem is that I loose the PID in this long pipe and I'm not sure how to print it.
But if your problem is "how many springboot apps", then it might not be an issue. I'm also not sure if the classes may appear twice when using jcmd VM.class_hierarchy, but it doesn't look like it.
Note: This works on JDK 11. I tried jmap first, but that doesn't work for me on JDK 11 for some reason.

Use docker-machine create from java

I have an application that (I want to) uses Java to start and stop Docker containers. It seems that the way to do this is using docker-machine create, which works fine when I test from the command line.
However, when running using Commons-Exec from Java I get the error:
(aa4567c1-058f-46ae-9e97-56fb8b45211c) Creating SSH key...
Error creating machine: Error in driver during machine creation: /usr/local/bin/VBoxManage modifyvm aa4567c1-058f-46ae-9e97-56fb8b45211c --firmware bios --bioslogofadein off --bioslogofadeout off --bioslogodisplaytime 0 --biosbootmenu disabled --ostype Linux26_64 --cpus 1 --memory 1024 --acpi on --ioapic on --rtcuseutc on --natdnshostresolver1 off --natdnsproxy1 on --cpuhotplug off --pae on --hpet on --hwvirtex on --nestedpaging on --largepages on --vtxvpid on --accelerate3d off --boot1 dvd failed:
VBoxManage: error: Could not find a registered machine with UUID {aa4567c1-058f-46ae-9e97-56fb8b45211c}
VBoxManage: error: Details: code VBOX_E_OBJECT_NOT_FOUND (0x80bb0001), component VirtualBoxWrap, interface IVirtualBox, callee nsISupports
VBoxManage: error: Context: "FindMachine(Bstr(a->argv[0]).raw(), machine.asOutParam())" at line 500 of file VBoxManageModifyVM.cpp
I have set my VBOX_USER_HOME variable in an initializationScript that I'm using to start the machine:
export WORKERID=$1
export VBOX_USER_HOME=/Users/me/Library/VirtualBox
# create the machine
docker-machine create $WORKERID && \ # create the worker using docker-machine
eval $(docker-machine env $WORKERID) && \ # load the env of the newly created machine
docker run -d myimage
And I'm executing this from Java via the Commons Exec CommandLine class:
CommandLine cmdline = new CommandLine("/bin/sh");
cmdline.addArgument(initializeWorkerScript.getAbsolutePath());
cmdline.addArgument("test");
Executor executor = new DefaultExecutor();
If there is another library that can interface with docker-machine from Java I'm happy to use that, or to change out Commons Exec if that's the issue (though I don't understand why). The basic requirement is that I have some way to get docker-machine to create a machine using Java and then later to be able to use docker-machine to stop that machine.
As it turns out the example that I posted should work, the issue that I was having is that I was provisioning machines with a UUID name. That name contained dash (-) characters which apparently break VBoxManage. This might be because of some kind of path problem but I'm just speculating. When I changed my UUID to have dot (.) instead of dash it loaded and started the machine just fine.
I'm happy to remove this post if the moderators want, but will leave it up here in case people are looking for solutions to problems with docker-machine create naming issues.

Using Weka gives different results between GUI and API implementation

I am using Weka to do classification of my dataset. First I did this using the GUI giving me some results (Accurracy, ROC, ...). Now that I'm using the API to implement a small framework around WEKA, I run the exact same configuration yet getting different results.
Let me give you an example:
Config of .ARFF file in GUI:
#relation 'QueryResult-weka.filters.unsupervised.attribute.NominalToString-Clast
-weka.filters.unsupervised.attribute.StringToWordVector-R2-W1000-prune-rate-1.0-N0
-stemmerweka.core.stemmers.NullStemmer-M1-O-tokenizerweka.core.tokenizers.WordTokenizer -delimiters \",
-weka.filters.unsupervised.attribute.StringToNominal-R2-last
-weka.filters.unsupervised.attribute.NumericToBinary-unset-class-temporarily
-weka.filters.unsupervised.attribute.NominalToString-Cfirst
-weka.filters.unsupervised.attribute.StringToWordVector-R1-W1000000-prune-rate-1.0-C-T-I-N0-L-S
-stemmerweka.core.stemmers.NullStemmer-M1-stopwords/Users/stopwds.txt-tokenizerweka.core.tokenizers.WordTokenizer
-delimiters \" \\r \\t.,;:\\\'\\\"()?!-/<>[]\\t\\r\\n\"-weka.filters.unsupervised.attribute.Remove-R120-1964
-weka.filters.unsupervised.attribute.Remove-R121-123'
As I said, using the API I use same config:
#relation 'QueryResult-weka.filters.unsupervised.attribute.NominalToString-Clast
-weka.filters.unsupervised.attribute.StringToWordVector-R2-W1000-prune-rate-1.0-N0
-stemmerweka.core.stemmers.NullStemmer-M1-O-tokenizerweka.core.tokenizers.WordTokenizer -delimiters \",
-weka.filters.unsupervised.attribute.StringToNominal-R2-last
-weka.filters.unsupervised.attribute.NumericToBinary-unset-class-temporarily
-weka.filters.unsupervised.attribute.NominalToString-Cfirst
-weka.filters.unsupervised.attribute.StringToWordVector-R1-W1000000-prune-rate-1.0-C-T-I-N0-L-S
-stemmerweka.core.stemmers.NullStemmer-M1-stopwords/Users/stopwds.txt-tokenizerweka.core.tokenizers.WordTokenizer
-delimiters \" \\r \\t.,;:\\\'\\\"()?!-/<>[]\\t\\r\\n\"-weka.filters.unsupervised.attribute.Remove-R120-1964
-weka.filters.unsupervised.attribute.Remove-R121-123'
Now when I run the classifier, again with same configurations, I get different output! However, the funny part is when I load the .ARFF file generated from my Java code after running the config and then train the classifier there, I DO get the exact same output as expected/required.
Can please someone explain what I'm doing wrong and why the output is different? I read other posts such as link where a similar problem occurred.
--
To clarify, here is the config of my classifier in the GUI:
weka.classifiers.lazy.IBk -K 30 -W 0 -I -A "weka.core.neighboursearch.LinearNNSearch -A \"weka.core.EuclideanDistance -R first-last\""
And this is how it is in my Java code:
iBk.setOptions(weka.core.Utils.splitOptions("-K 30 -W 0 -I -A \"weka.core.neighboursearch.LinearNNSearch -A \\\"weka.core.EuclideanDistance -R first-last\\\"\""));

tdbloader on Cygwin: Gettging FileNotFoundException: d:\cygdrive\d\....\node2id.idn

I am completely new to Jena/TDB. All I want to do is to load data from some sample rdf, N3 etc file using tdb scripts or through java api.
I am tried to use tbdloader on Cygwin to load data (tdb-0.9.0, on Windows XP with IBM Java 1.6). Following are the command that I ran:
$ export TDBROOT=/cygdrive/d/Project/Store_DB/jena-tdb-0.9.0-incubating
$ export PATH=$TDBROOT/bin:$PATH
I also changed classpath for java in the tdbloader script as mentioned at tdbloader on Cygwin: java.lang.NoClassDefFoundError :
exec java $JVM_ARGS $SOCKS -cp "PATH_OF_JAR_FILES" "tdb.$TDB_CMD" $TDB_SPEC "$#"
So when I run $ tdbloader --help it shows the help correctly.
But when I run
$ tdbloader --loc /cygdrive/d/Project/Store_DB/data1
OR
$ tdbloader --loc /cygdrive/d/Project/Store_DB/data1 test.rdf
I am getting following exception:
com.hp.hpl.jena.tdb.base.file.FileException: Failed to open: d:\cygdrive\d\Project\Store_DB\data1\node2id.idn (mode=rw)
at com.hp.hpl.jena.tdb.base.file.ChannelManager.open$(ChannelManager.java:83)
at com.hp.hpl.jena.tdb.base.file.ChannelManager.openref$(ChannelManager.java:58)
at com.hp.hpl.jena.tdb.base.file.ChannelManager.acquire(ChannelManager.java:47)
at com.hp.hpl.jena.tdb.base.file.FileBase.<init>(FileBase.java:57)
at com.hp.hpl.jena.tdb.base.file.FileBase.<init>(FileBase.java:46)
at com.hp.hpl.jena.tdb.base.file.FileBase.create(FileBase.java:41)
at com.hp.hpl.jena.tdb.base.file.BlockAccessBase.<init>(BlockAccessBase.java:46)
at com.hp.hpl.jena.tdb.base.block.BlockMgrFactory.createStdFile(BlockMgrFactory.java:98)
at com.hp.hpl.jena.tdb.base.block.BlockMgrFactory.createFile(BlockMgrFactory.java:82)
at com.hp.hpl.jena.tdb.base.block.BlockMgrFactory.create(BlockMgrFactory.java:58)
at com.hp.hpl.jena.tdb.setup.Builder$BlockMgrBuilderStd.buildBlockMgr(Builder.java:196)
at com.hp.hpl.jena.tdb.setup.Builder$RangeIndexBuilderStd.createBPTree(Builder.java:165)
at com.hp.hpl.jena.tdb.setup.Builder$RangeIndexBuilderStd.buildRangeIndex(Builder.java:134)
at com.hp.hpl.jena.tdb.setup.Builder$IndexBuilderStd.buildIndex(Builder.java:112)
at com.hp.hpl.jena.tdb.setup.Builder$NodeTableBuilderStd.buildNodeTable(Builder.java:85)
at com.hp.hpl.jena.tdb.setup.DatasetBuilderStd$NodeTableBuilderRecorder.buildNodeTable(DatasetBuilderStd.java:389)
at com.hp.hpl.jena.tdb.setup.DatasetBuilderStd.makeNodeTable(DatasetBuilderStd.java:300)
at com.hp.hpl.jena.tdb.setup.DatasetBuilderStd._build(DatasetBuilderStd.java:167)
at com.hp.hpl.jena.tdb.setup.DatasetBuilderStd.build(DatasetBuilderStd.java:157)
at com.hp.hpl.jena.tdb.setup.DatasetBuilderStd.build(DatasetBuilderStd.java:70)
at com.hp.hpl.jena.tdb.StoreConnection.make(StoreConnection.java:132)
at com.hp.hpl.jena.tdb.transaction.DatasetGraphTransaction.<init>(DatasetGraphTransaction.java:46)
at com.hp.hpl.jena.tdb.sys.TDBMakerTxn._create(TDBMakerTxn.java:50)
at com.hp.hpl.jena.tdb.sys.TDBMakerTxn.createDatasetGraph(TDBMakerTxn.java:38)
at com.hp.hpl.jena.tdb.TDBFactory._createDatasetGraph(TDBFactory.java:166)
at com.hp.hpl.jena.tdb.TDBFactory.createDatasetGraph(TDBFactory.java:74)
at com.hp.hpl.jena.tdb.TDBFactory.createDataset(TDBFactory.java:53)
at tdb.cmdline.ModTDBDataset.createDataset(ModTDBDataset.java:95)
at arq.cmdline.ModDataset.getDataset(ModDataset.java:34)
at tdb.cmdline.CmdTDB.getDataset(CmdTDB.java:137)
at tdb.cmdline.CmdTDB.getDatasetGraph(CmdTDB.java:126)
at tdb.cmdline.CmdTDB.getDatasetGraphTDB(CmdTDB.java:131)
at tdb.tdbloader.loadQuads(tdbloader.java:163)
at tdb.tdbloader.exec(tdbloader.java:122)
at arq.cmdline.CmdMain.mainMethod(CmdMain.java:97)
at arq.cmdline.CmdMain.mainRun(CmdMain.java:59)
at arq.cmdline.CmdMain.mainRun(CmdMain.java:46)
at tdb.tdbloader.main(tdbloader.java:53)
Caused by: java.io.FileNotFoundException: d:\cygdrive\d\Project\Store_DB\data1\node2id.idn (The system cannot find the path specified.)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:222)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:107)
at com.hp.hpl.jena.tdb.base.file.ChannelManager.open$(ChannelManager.java:80)
... 37 more
I am not sure what node2id.idn file is and why is it expecting it?
The file node2id.idn is one of TDB's internal index files. It's not something that you have to create or manage for yourself. I've just tried tdbloader on cygwin myself, it it worked OK for me. I can think of two basic possibilities:
your disk is full
the TDB index is corrupted
If this is the first file you are loading into an otherwise emtpy TDB, the second possibility is unlikely. If you are loading into a non-empty TDB, try deleting the TDB image and starting again. Note that TDB by itself does not manage concurrent writes: if you have more than one process writing to a single TDB image, you must handle locking at the application level, or use TDB's transactions.
The final possibility, of course, is that your disk is flaky. You might want to try your code on another machine.
If none of these suggestions help, please send a complete minimal test case to the Jena users list.

Command-line JMX Client set value

I m using Command-line JMX Client to be able to query ActiveMQ Server. At the same time I want to be able to set values dynamically to the server. such as MemoryLimit.
Is it possible to set values via Command-Line JMX client, if yes , how can i set the memory limit?
This is how i was able to query.
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 org.apache.activemq:BrokerName=defaultBroker,Destination=Testing,Type=Queue MemoryLimit
but how can i set memorylimit?
I tried below:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 org.apache.activemq:BrokerName=defaultBroker,Destination=Testing,Type=Queue setMemoryLimit=300000`
and failed as below.
11/18/2011 11:56:28 -0800 org.archive.jmx.Client setMemoryLimit=300000: Operation setMemoryLimit not found.
Edit
I'd recommend dropping that jmxclient and switching to:
http://wiki.cyclopsgroup.org/jmxterm
It looks to be supported and better documented. I suspect that it will work and give you access to the setters -- if they exist.
If the set method does exist then the following should work:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 \
org.apache.activemq:BrokerName=defaultBroker,Destination=Testing,Type=Queue \
setMemoryLimit=...
Here are the docs:
http://crawler.archive.org/cmdline-jmxclient/
To find out which attributes are available for setting and getting, I'd use jconsole. If you are using a Java6+ jconsole, you field click on the bean you want to get information from. That should show you the ObjectName to use on the command line. Then if you open the attributes list, the name of the attribute should have a corresponding get method. If the value is colored blue then there should be a corresponding set method.
For example, if you open up the java.lang folder in jconsole, you should be able to click on ClassLoading. That shows you the ObjectName to use is java.lang:type=ClassLoading. You can then do the following to list the various attributes and operations available:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 \
java.lang:type=ClassLoading
You should see the getters and the setters. Here's how you get the Verbose attribute:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 \
java.lang:type=ClassLoading Verbose
For some reason my version cmdline-jmxclient does not know how to do boolean type so it doesn't show up as a setter. If it did you should be able to do:
java -jar cmdline-jmxclient-0.10.3.jar - localhost:1099 \
java.lang:type=ClassLoading setVerbose=true

Categories

Resources