I'm writing an IntelliJ-Plugin to analyse java-program code. Thus i use Soot to write static analyses. Every time a user triggers the analyse-action of my plugin, I take the current VirtualFile of the current context like this:
FileEditorManager manager = FileEditorManager.getInstance(e.getProject());
VirtualFile files[] = manager.getSelectedFiles();
toAnalyse = files[0]; [...]
When I check the content of this file all changes are applied. After this I'm loading the class I want to analyse in Soot.
String dir = toAnalyse.getParent().getPath() ;
Options.v().setPhaseOption("jb", "use-original-names");
Options.v().set_soot_classpath( System.getProperty("java.home")+";"+ dir);
c = Scene.v().loadClassAndSupport(name);
/*no analyse c*/
This works perfectly for me. But now to my issue:
If i change sth. in test instance of my plugin and trigger the same analysis again, nothing changes.
What have i tried so far?
I set following options:
Options.v().set_dump_body( Arrays.asList("jb"));
Options.v().set_dump_cfg( Arrays.asList("jb"));
Options.v().set_allow_phantom_refs(true);
Options.v().set_whole_program(true);
I also removed all classes by hand
like this:
Chain<SootClass> classes = Scene.v().getClasses();
Stack<SootClass> stack = new Stack<>();
for(SootClass s : classes)
stack.push(s);
while(!stack.empty())
Scene.v().removeClass(stack.pop());
and started the program again.
I solved this issue.
SootClass c = Scene.v().loadClassAndSupport(name);
// ...
c.setResolvingLevel(0);
G.reset();
G.reset() resets all singleton instances.
Therefore all cached results will be overwritten by calling this action again.
public static Scene v() {
return G.v().soot_Scene();
}
this.instance_soot_Scene is null after calling G.reset().
Therefore the following code:
public Scene soot_Scene() {
if(this.instance_soot_Scene == null) {
synchronized(this) {
if(this.instance_soot_Scene == null) {
this.instance_soot_Scene = new Scene(this.g);
}
}
}
return this.instance_soot_Scene;
}
returns a new instance with an empty result cache.
Related
I migrated older printer API code to Java 8, and the following warning appears:
Access restriction: The method 'AppContext.getAppContext()' is not API (restriction on required library 'C:\Program Files\Java\jre1.8.0_51\lib\rt.jar')
It is due to this code (originally sourced from this SO question):
/**
* Printer list does not refresh itself; need to run this to refresh if necessary.
*/
public static void refreshSystemPrinterList() {
Class[] classes = PrintServiceLookup.class.getDeclaredClasses();
for (int i = 0; i < classes.length; i++) {
if ("javax.print.PrintServiceLookup$Services".equals(classes[i].getName())) {
AppContext.getAppContext().remove(classes[i]); // the line that throws the warning
break;
}
}
As I understand it, PrintServiceLookup loads a list of visible printers when it is classloaded, but it apparently does not refresh this list, or have the ability trigger a refresh. The way for a long-running application to refresh the list would be to either unload the class, which is what the code is doing, or restart itself.
Mild research on the warning reveals come Java 9, AppContext.getAppContext() will be inaccessible. Without further research, my current remediation idea is to use an accessible classloader for loading this class, and purging the classloader when this method is called.
Ultimately, I want to know what I need to do to properly replace this. Currently running on Windows, may be moving to Linux ; I see a lot of updates to this SO question regarding the Linux implementation.
PrintServiceLookupProvider (the only concrete implementation of PrintServiceLookup provides a thread that is supposed to do this.
It loops infinitely checking for changes, and calls refreshServices if there is one.
class PrinterChangeListener implements Runnable {
long chgObj;
PrinterChangeListener() {
chgObj = notifyFirstPrinterChange(null);
}
#Override
public void run() {
if (chgObj != -1) {
while (true) {
// wait for configuration to change
if (notifyPrinterChange(chgObj) != 0) {
try {
refreshServices();
} catch (SecurityException se) {
break;
}
} else {
notifyClosePrinterChange(chgObj);
break;
}
}
}
}
}
Started here:
Thread thr = new Thread(null, new PrinterChangeListener(), "PrinterListener", 0, false);
thr.setDaemon(true);
thr.start();
If you are having problems with this not working, you should look into why notifyPrinterChange is not indicating that something changed. It's a native method, so the implementation will depend on your OS.
Unfortunately you cannot even use reflection to call refreshServices manually, since reflection over Sun modules is restricted (you can override it, but if you were doing that then you may as well override the export of AppContext)
Suppose I have something as follows where DataImporter is a utility to retrieve data from the file system and has child data importers within it for retrieving data from the sub folders based on the category string:
List<String> categories = getCategories();
boolean doesChildImporterExist = false;
for (String category : categories)
{
DataImporter childDataImporter=importer.getChild(category);
if (childDataImporter != null)
{
doesChildImporterExist = true;
populateImportedData(childDataImporter.importData());
}
}
if(!doesChildImporterExist)
populateImportedData(importer.importData());
I know the other option is to construct a List of child data importers and check for its size, if it is 0 or not and based on that import the data using the desired importer. However, I'm trying to understand what is wrong with using the boolean flag here?
Assume that the code above is within a method and using Java 1.7.
When you use a boolean flag in a method as a branch decider (not the best terminology),
you are actually taking the functionality of two different methods and smashing them into one method.
Often,
the better solution is to have a method for the shared functionality and a second method for the super set functionality.
For example:
public DataImporter doYourCategoryStuff()
{
List<String> categories = getCategories();
... blah including the for loop.
return theDataImporter;
}
public void doAllTheStuffs()
{
final DataImporter theDataImporter;
theDataImporter.doYourCategorStuff();
populateImportedData(theDataImporter.importData());
}
Edit
More to the point in your code.
In your code,
the boolean flag indicates "I did something to a child importer and need to update parent importer".
In this case you are smashing "identify things to update" and "do the update" together;
split them.
Consider something like this:
Set<DataImporter> updateSet = new HashSet<>();
for (category for loop)
{
final DataImporter child = importer.getChild(category);
if (child != null)
{
updateSet.add(child);
updateSet.add(importer);
}
}
for (final DataImporter current : updateSet)
{
current.importData();
}
Even though the add(importer) (the parent) may be called multiple times,
the set will only ever contain one instance of each DataImporter.
This should be reasonable even if you don't implement hashCode and equals on DataImporter, since the parent reference will always be the same.
I'm dynamically loading classes on Android through the following code sniplet.
if(classes.size() > 0) {
// Located classes.load and scan them for interfaces.
DexClassLoader dx = new DexClassLoader(szPath,outdex,null, c.getClassLoader());
for(String sz : classes) {
Class<?> cls = dx.loadClass(sz);
for(Class<?> i : cls.getInterfaces()) {
if(i.getName().contains("IPinPad") == true) {
// This is a PinPad.
return (IPinPad)cls.newInstance();
}
}
}
}
classes contains a list of classes descovered in the dex file from previous run code. purpose od this code is to return object instances which implements the IPinPad interface declaration. This all works fine, but in addition I'd like to grab the byte code for the cls.newInstance() object. How should I do this?
I've been playing around with cls.getClassLoader().getResourceAsStream(); but it always returns a null stream, unsure how to specify the resourcename for the class.
You can use dexlib2 (part of smali/baksmali) in order to load and read the dalvik bytecode in a dex file. And yes, it should be usable in an Android app as well.
DexFile dexFile = DexFileFactory.loadDexFile("/blah/blah.dex", android.os.Build.VERSION.SDK_INT);
for (ClassDef classDef: dexFile.getClasses()) {
if (classDef.getType().equals("Lthe/class/to/look/for;")) {
// handle/inspect/process the class as needed
}
}
Sorry I can't come up with a better question title because it's pretty hard to describe...
I was inspecting Android's source (4.4 KK), the View class in particular and this showed up:
// .... lots of stuff....
AttachInfo mAttachInfo;
// .... lots of stuff....
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
That's the View.post(Runnable) that we all love to use whenever we need something to run on the UI thread.
The thing I don't understand here is why do they create another local reference of attachInfo?
Why don't they do it like:
if (mAttachInfo != null) {
return mAttachInfo.mHandler.post(action);
}
Other than making attachInfo immutable in the method scope to prevent bugs(even thought they can still accidentally access mAttachInfo), I don't think there's any reason to do this.
Another possibility would be to shorten names, but I don't think it's worth shorting 1 character.
Is this a design pattern?
EDIT:
further inspecting the source reveals that they use this "pattern" in many places:
public void postInvalidateOnAnimation() {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
}
}
Basically, they use it in almost every postXXXXXX() method.
EDIT2:
#CommonsWare pointed out that it might be used for anonymous inner class in previous versions, I checked the source of 1.5(Cupcake) ~ 2.3.3(Gingerbread) and this is what post() looks like
public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
I still don't see why....
Bear in mind that post() may be called from background threads at the same time as mAttachInfo is updated on the UI thread. The code that was used up to Android 2.3.3 could throw an NPE if mAttachInfo was set to null after the if (mAttachInfo != null) check and before mAttachInfo.mHandler was accessed.
The current code avoids the NPE by taking a snapshot of mAttachInfo that doesn't change for the lifetime of the method.
The local variable doesn't strictly need to be final, but declaring it final makes it extra clear that it won't become null after the if (attachInfo != null) check.
I want to call the Groovy scripts from Java and refresh the Groovy scripts periodically.
For example ,
public class AppTest {
public static void main(String args[]) throws Exception {
TestVO test = new TestVO();
AnotherInput input = new AnotherInput();
test.setName("Maruthi");
input.setCity("Newark");
GroovyClassLoader loader = new GroovyClassLoader(AppTest.class.getClassLoader());
Class groovyClass = loader.parseClass(new File("src/main/resources/groovy/MyTestGroovy.groovy"));
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] inputs = {test,null};
Map<String,String> result = (Map<String, String>)groovyObject.invokeMethod("checkInput", inputs);
System.out.println(result);
}
}
And my Groovy script is
class MyTestGroovy {
def x = "Maruthi";
def checkInput = { TestVO input,AnotherInput city ->
if(input.getName().equals(x)) {
input.setName("Deepan");
println "Name changed Please check the name";
} else {
println "Still Maruthi Rocks";
}
Map<String, String> result = new HashMap<String,String>();
result.put("Status", "Success");
if(city != null && city.getCity().equalsIgnoreCase("Newark")) {
result.put("requested_State", "Newark");
}
return result;
}
def executeTest = {
println("Test Executed");
}
}
How efficient my memory would be managed when I create multiple instances of groovy script and execute the script. Is it advisable to use a number of Groovy scripts as my customized rule engine. Please advise.
It is usually better to have several instances of the same script, than parsing the class every time you want to create an instance. Performance wise that is because compiling the script takes some time, you have to pay in addition to creating an instance. Memory wise you use up the number of available classes up faster. Even if old classes are collected, if you have many scripts active, it can happen... though that normally means hundreds or even thousands of them (depends on the jvm version and your memory settings)
Of course, once the script changed, you will have to recompile the class anyway. So if in your scenario you will have only one instance of the class active at the same time, and a new instance is only required after a change to the source, you can recompile every time.
I mention that especially, because you might even be able to write the script in a way, that let's you reuse the same instance. But it is of course beyond the scope of this question.