├── .gitignore ├── .travis.yml ├── LICENSE ├── LICENSE.md ├── README.md ├── deployment ├── deploy.sh ├── settings.xml └── signingkey.asc.enc ├── pom.xml ├── vmvm-ant-junit-formatter ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── edu │ └── columbia │ └── cs │ └── psl │ └── vmvm │ ├── AntJUnitTestListener.java │ ├── MvnReportingListener.java │ ├── MvnVMVMListener.java │ └── TestReportingListener.java ├── vmvm-internal-static-detector ├── bin │ └── log4j.properties ├── lib │ ├── asm-all-4.0.jar │ ├── asm-src.zip │ └── log4j-1.2.16.jar ├── pom.xml ├── src │ └── main │ │ ├── java │ │ └── edu │ │ │ └── columbia │ │ │ └── cs │ │ │ └── psl │ │ │ └── vmvm │ │ │ └── util │ │ │ └── StaticPutDetector.java │ │ └── resources │ │ └── log4j.properties ├── static-mod └── vmvm-internal-static-detector.iml └── vmvm ├── .gitignore ├── pom.xml └── src ├── main ├── java │ ├── edu │ │ └── columbia │ │ │ └── cs │ │ │ └── psl │ │ │ └── vmvm │ │ │ └── runtime │ │ │ ├── AdditionalInterfaceClassloader.java │ │ │ ├── ConsumerUtils.java │ │ │ ├── FieldReflectionWrapper.java │ │ │ ├── Instrumenter.java │ │ │ ├── JUnitInterceptingClassVisitor.java │ │ │ ├── PreMain.java │ │ │ ├── VMVMClassFileTransformer.java │ │ │ └── inst │ │ │ ├── ClassReinitCV.java │ │ │ ├── Constants.java │ │ │ ├── LabelRemappingMV.java │ │ │ ├── PlaceholderClasswriter.java │ │ │ ├── PutStaticHelperMV.java │ │ │ ├── ReflectionFixingCV.java │ │ │ ├── ReflectionFixingMV.java │ │ │ ├── ReinitCheckForceMV.java │ │ │ ├── SystemPropertyLogger.java │ │ │ └── Utils.java │ └── java │ │ └── edu │ │ └── columbia │ │ └── cs │ │ └── psl │ │ └── vmvm │ │ └── runtime │ │ ├── InterfaceReinitializer.java │ │ ├── MutableInstance.java │ │ ├── ReflectionWrapper.java │ │ ├── Reinitializer.java │ │ └── VMVMInstrumented.java └── resources │ └── java │ └── edu │ └── columbia │ └── cs │ └── psl │ └── vmvm │ └── runtime │ ├── ignored-clinits │ └── internal-statics └── test └── java └── edu └── columbia └── cs └── psl ├── test └── vmvm │ ├── EnumITCase.java │ ├── EvilInterface.java │ ├── InternalStaticITCase.java │ ├── OtherClass.java │ ├── OtherOtherClass.java │ ├── ReflectionITCase.java │ ├── ReinitializerITCase.java │ ├── SystemPropertiesITCase.java │ └── classes │ ├── ClassWithNoInterfaces.java │ ├── ClassWithOneSField.java │ ├── EEnum.java │ ├── Foo.java │ ├── IFace.java │ ├── LaterClass.java │ ├── SubClassWithAnotherSField.java │ └── TryCatchInInitClass.java └── vmvm └── testsupport └── FieldGetter.java /.gitignore: -------------------------------------------------------------------------------- 1 | framework/bin 2 | exp 3 | *.class 4 | *.log 5 | /bin 6 | experiments/ 7 | **/target 8 | 9 | # Eclipse files 10 | **/.settings/ 11 | **/.project 12 | **/.classpath 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | jdk: oraclejdk8 4 | script: mvn verify 5 | deploy: 6 | provider: script 7 | skip_cleanup: true 8 | script: cd $TRAVIS_BUILD_DIR; bash deployment/deploy.sh 9 | on: 10 | branch: master 11 | env: 12 | global: 13 | - secure: jKeinjZsevIWoUvHDrgDE4gfkQR6Z4rB5vIF0QQEltWcWOHZXLGhxE7ecy6/ff1Z5gzZtCTeneLsthkzqrbzm8FzVAhbYJ9WwpENz0spVVyjnHUU7W72tI5AKlLNTonJDJOogENhT95ivgZ3/cAPMYw1qnDKCNfdBwfT3Il39UY= 14 | - secure: G4admxhpOLcuQ6kpUtMNW44VPkg01/Emb4geuZQ7fnHuMJ/G1bkRemtP1/7eLeoBNjTWAATKWt9uHdv9PwsqvoYVxndstxZ6lhjdaPL4KHvxbfhnckm+h4ZBMHH1li8pDX6T0GB1uH/SAx/ML/v3w5+XKZfqtsYS1EPRt0ylQbM= 15 | - secure: TGMDGOLnCg1X04Binmg9QSPxdjo77iwJN3A1qfCAPa+uM6IaYHoIUBXZr8z9nX6gDaVPxmjErlpByDYMt/Uh8sNEY8+L85PAF1L4Fg94GO5edWgYUUGMvwcqAIwVwvZZSteXqJpUaWAlVC1lxUn7AsiJ+wdonGHREzO++SxeZYo= 16 | before_install: 17 | - openssl aes-256-cbc -K $encrypted_df4dabc64bbd_key -iv $encrypted_df4dabc64bbd_iv 18 | -in deployment/signingkey.asc.enc -out deployment/signingkey.asc -d 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Programming-Systems-Lab/vmvm/07a36dc21373147c50ceacd7bff2b2e7a86c8780/LICENSE -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This software is released under the MIT license: 2 | 3 | Copyright © 2013, by The Trustees of Columbia University in the City of New York. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | 12 | 13 | This project makes use of the following libraries: 14 | * [ASM](http://asm.ow2.org/license.html), (c) 2000-2011 INRIA, France Telecom, [license](http://asm.ow2.org/license.html) 15 | * [Log4j](http://logging.apache.org/log4j/), (c) 1999-2012, Apache Software Foundation, released under the Apache License 2.0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #VMVM - Unit Test Virtualization for Java [![Build Status](https://travis-ci.org/Programming-Systems-Lab/vmvm.svg?branch=vmvm2)](https://travis-ci.org/Programming-Systems-Lab/vmvm) 2 | ========== 3 | **VMVM** is a system for isolating unit tests with very low overhead. 4 | 5 | This repository contains the source and a [runnable binary](http://jonbell.net/vmvm/vmvm.jar) for **VMVM**. 6 | 7 | 8 | ###For more information 9 | Please refer to our [ICSE '14 Paper](http://jonbell.net/publications/vmvm) or email [Jonathan Bell](mailto:jbell@cs.columbia.edu). Note that this new version of VMVM (VMVM 2) is somewhat different in architecture than described in our publication: we have removed the need for the pre-instrumentation phase, which makes using it in practice significantly easier. VMVM 2 requires you to use a Java 8 JRE (or newer) when running tests (but is compatible with older code). 10 | 11 | Running 12 | ----- 13 | 14 | ### Modifying your build scripts 15 | To automatically have VMVM be called by ant, modify the `junit` task of your `build.xml` file to add the following elements: 16 | 17 | ```xml 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ``` 26 | 27 | Make sure that the paths are correct to [vmvm.jar](http://jonbell.net/vmvm/vmvm.jar) and [ant-mvn-formatter.jar](http://jonbell.net/vmvm/ant-mvn-formatter.jar). Also be sure that your `junit` task has the argument `forkMode="once"` (e.g. that it won't fork a new process for each test, defating the purpose of VMVM). 28 | 29 | That's it. 30 | 31 | To automatically have VMVM be called by mvn, modify the `pom.xml` file for your project as follows: 32 | 33 | 1. Make sure that you are using a recent version of the surefire plugin (e.g., 2.15) 34 | 2. Declare the VMVM dependencies: 35 | 36 | ```xml 37 | 38 | edu.columbia.cs.psl.vmvm 39 | vmvm 40 | 1.0.0-SNAPSHOT 41 | test 42 | 43 | 44 | edu.columbia.cs.psl.vmvm 45 | vmvm-ant-junit-formatter 46 | 1.0.0-SNAPSHOT 47 | test 48 | 49 | ``` 50 | 51 | 3. Register the VMVM test listener with surefire. If you don't have any other properties set for the surefire plugin, then that would look like this: 52 | 53 | ```xml 54 | 55 | -Xbootclasspath/p:vmvm.jar -javaagent:vmvm.jar 56 | 57 | 58 | listener 59 | edu.columbia.cs.psl.vmvm.MvnVMVMListener 60 | 61 | 62 | 63 | ``` 64 | 65 | Here's an example of a mininal `pom.xml` block declaring the Maven Surefire plugin using the VMVM with it: 66 | 67 | ```xml 68 | 69 | org.apache.maven.plugins 70 | maven-surefire-plugin 71 | 2.18.1 72 | 73 | -Xbootclasspath/p:vmvm.jar -javaagent:vmvm.jar 74 | 75 | 76 | listener 77 | edu.columbia.cs.psl.vmvm.MvnVMVMListener 78 | 79 | 80 | 81 | 82 | ``` 83 | 84 | Citing 85 | ----- 86 | If you would like to reference VMVM in an academic publication, please cite our ICSE '14 publication: 87 | ``` 88 | 89 | @inproceedings{vmvm, 90 | Title = {Unit Test Virtualization with VMVM}, 91 | Author = {\textbf{Bell, Jonathan} and Kaiser, Gail}, 92 | Booktitle = {Proceedings of the 2014 International Conference on Software Engineering}, 93 | Location = {Hyderabad, India}, 94 | Month = {Jun}, 95 | Publisher = {IEEE Press}, 96 | Series = {ICSE 2014}, 97 | Url = {http://jonbell.net/publications/vmvm}, 98 | Year = {2014} 99 | } 100 | ``` 101 | 102 | 103 | In case of problems.. 104 | ----- 105 | We have verified that VMVM works with the following applications. If you notice any incompatibilities with it, please email [Jonathan Bell](mailto:jbell@cs.columbia.edu), (or, fix the bug yourself and send a patch :P). 106 | 107 | Applications that we have tested with VMVM (and are known to work): 108 | * [Apache Ivy](http://ant.apache.org/ivy/) 109 | * [Apache Nutch](http://nutch.apache.org/) 110 | * [Apache River](http://river.apache.org/) 111 | * [Apache Tomcat](http://tomcat.apache.org/) 112 | * [betterFORM](http://www.betterform.de/en/index.html) 113 | * [Bristlecone](http://www.ohloh.net/p/bristlecone) 114 | * [btrace](https://kenai.com/projects/btrace) 115 | * [Closure Compiler](http://commons.apache.org/proper/commons-jci/) 116 | * [Commons Codec](http://commons.apache.org/proper/commons-codec/) 117 | * [Commons IO](http://commons.apache.org/proper/commons-io/) 118 | * [Commons Validator](http://commons.apache.org/proper/commons-validator/) 119 | * [FreeRapid Downloader](http://wordrider.net/freerapid/) 120 | * [gedcom4j](http://gedcom4j.org/main/) 121 | * [JAXX](http://nuiton.org/projects/jaxx) 122 | * [Jetty](http://www.eclipse.org/jetty/jtor* ) 123 | * [JTor](https://github.com/brl/JTor) 124 | * [mkgmap](http://wiki.openstreetmap.org/wiki/Mkgmap) 125 | * [Openfire](http://www.igniterealtime.org/projects/openfire/) 126 | * [Trove, for Java](http://trove.starlight-systems.com/) 127 | * [Universal Password Mananager (UPM)](http://upm.sourceforge.net/) 128 | 129 | License 130 | ------ 131 | This software is released under the MIT license. 132 | 133 | Copyright (c) 2013, by The Trustees of Columbia University in the City of New York. 134 | 135 | Permission is hereby granted, free of charge, to any person obtaining 136 | a copy of this software and associated documentation files (the 137 | "Software"), to deal in the Software without restriction, including 138 | without limitation the rights to use, copy, modify, merge, publish, 139 | distribute, sublicense, and/or sell copies of the Software, and to 140 | permit persons to whom the Software is furnished to do so, subject to 141 | the following conditions: 142 | 143 | The above copyright notice and this permission notice shall be 144 | included in all copies or substantial portions of the Software. 145 | 146 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 147 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 148 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 149 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 150 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 151 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 152 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 153 | 154 | 155 | Acknowledgements 156 | ----- 157 | This project makes use of the following libraries: 158 | * [ASM](http://asm.ow2.org/license.html), (c) 2000-2011 INRIA, France Telecom, [license](http://asm.ow2.org/license.html) 159 | * [Log4j](http://logging.apache.org/log4j/), (c) 1999-2012, Apache Software Foundation, released under the Apache License 2.0 160 | 161 | The authors of this software are [Jonathan Bell](http://jonbell.net) and [Gail Kaiser](http://www.cs.columbia.edu/~kaiser/). The authors are members of the [Programming Systems Laboratory](http://www.psl.cs.columbia.edu/), funded in part by NSF CCF-1161079, NSF CNS-0905246, and NIH U54 CA121852. 162 | 163 | [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/cd95553682148d1cecb84c7edf60c780 "githalytics.com")](http://githalytics.com/Programming-Systems-Lab/vmvm) 164 | -------------------------------------------------------------------------------- /deployment/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gpg2 --keyring=$TRAVIS_BUILD_DIR/pubring.gpg --no-default-keyring --import $TRAVIS_BUILD_DIR/deployment/signingkey.asc; 4 | gpg2 --allow-secret-key-import --keyring=$TRAVIS_BUILD_DIR/secring.gpg --no-default-keyring --import $TRAVIS_BUILD_DIR/deployment/signingkey.asc; 5 | cd $TRAVIS_BUILD_DIR; 6 | mvn -DskipTests deploy --settings $TRAVIS_BUILD_DIR/deployment/settings.xml -Dgpg.executable=gpg2 -Dgpg.keyname=77787D71ED65A50488D41B82E876C482DFB8D3EB -Dgpg.passphrase=$PASSPHRASE -Dgpg.publicKeyring=$TRAVIS_BUILD_DIR/pubring.gpg -Dgpg.secretKeyring=$TRAVIS_BUILD_DIR/secring.gpg 7 | -------------------------------------------------------------------------------- /deployment/settings.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | ossrh 7 | ${env.SONATYPE_USERNAME} 8 | ${env.SONATYPE_PASSWORD} 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /deployment/signingkey.asc.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Programming-Systems-Lab/vmvm/07a36dc21373147c50ceacd7bff2b2e7a86c8780/deployment/signingkey.asc.enc -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | edu.gmu.swe.vmvm 7 | vmvm-base-pom 8 | ${project.groupId}::${project.artifactId} 9 | 2.0.0-SNAPSHOT 10 | pom 11 | 12 | 13 | Unit Test Virtualization for Java(tm) 14 | 15 | 16 | 17 | 18 | MIT license 19 | http://opensource.org/licenses/MIT 20 | repo 21 | 22 | 23 | 24 | 25 | scm:git:git://github.com/Programming-Systems-Lab/vmvm.git 26 | scm:git:git@github.com:Programming-Systems-Lab/vmvm.git 27 | https://github.com/Programming-Systems-Lab/vmvm 28 | 29 | 30 | 31 | UTF-8 32 | UTF-8 33 | 1.7 34 | ${java.source.version} 35 | 150 36 | 37 | ${project.basedir}/LICENSE.md 38 | 4.11 39 | 1.7.0 40 | 1.9.4 41 | 5.1.34 42 | 1.2.16 43 | 4.0 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | edu.gmu.swe.vmvm 53 | vmvm 54 | ${project.version} 55 | 56 | 57 | 58 | edu.gmu.swe.vmvm 59 | vmvm-ant-junit-formatter 60 | ${project.version} 61 | 62 | 63 | 64 | edu.gmu.swe.vmvm 65 | vmvm-internal-static-detector 66 | ${project.version} 67 | 68 | 69 | 70 | 71 | junit 72 | junit 73 | ${junit.version} 74 | 75 | 76 | 77 | ant 78 | ant 79 | ${ant.version} 80 | 81 | 82 | 83 | org.apache.ant 84 | ant-junit 85 | ${ant.junit.version} 86 | 87 | 88 | 89 | mysql 90 | mysql-connector-java 91 | ${mysql.connector.java.version} 92 | 93 | 94 | 95 | log4j 96 | log4j 97 | ${log4j.version} 98 | 99 | 100 | 101 | org.ow2.asm 102 | asm-all 103 | ${asm.all.version} 104 | 105 | 106 | 107 | 108 | 109 | 110 | vmvm 111 | vmvm-ant-junit-formatter 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | org.apache.maven.plugins 121 | maven-jar-plugin 122 | 2.6 123 | 124 | 125 | 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | jar 135 | 136 | jar 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | org.apache.maven.plugins 147 | maven-resources-plugin 148 | 2.7 149 | true 150 | 151 | ${project.build.sourceEncoding} 152 | 153 | 154 | 155 | 156 | org.apache.maven.plugins 157 | maven-compiler-plugin 158 | 3.2 159 | true 160 | 161 | ${project.build.sourceEncoding} 162 | ${java.source.version} 163 | ${java.target.version} 164 | true 165 | true 166 | ${java.source.line.length} 167 | false 168 | true 169 | -Xlint:all 170 | 171 | 172 | 173 | 174 | org.apache.maven.plugins 175 | maven-jar-plugin 176 | true 177 | 178 | 179 | 180 | true 181 | true 182 | true 183 | 184 | 185 | 186 | 187 | 188 | jar 189 | 190 | jar 191 | 192 | 193 | 194 | 195 | 196 | 197 | org.apache.maven.plugins 198 | maven-source-plugin 199 | 2.4 200 | true 201 | 202 | 203 | attach-sources 204 | verify 205 | 206 | jar-no-fork 207 | 208 | 209 | 210 | 211 | 212 | 213 | org.apache.maven.plugins 214 | maven-javadoc-plugin 215 | 2.10.2 216 | true 217 | 218 | 219 | attach-sources 220 | verify 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | release-sign-artifacts 229 | 230 | 231 | gpg.passphrase 232 | 233 | 234 | 235 | 236 | 237 | org.apache.maven.plugins 238 | maven-gpg-plugin 239 | 1.4 240 | 241 | 242 | sign-artifacts 243 | verify 244 | 245 | sign 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | ossrh 257 | https://oss.sonatype.org/content/repositories/snapshots 258 | 259 | 260 | ossrh 261 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 262 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | edu.gmu.swe.vmvm 6 | vmvm-base-pom 7 | 2.0.0-SNAPSHOT 8 | 9 | 10 | 4.0.0 11 | vmvm-ant-junit-formatter 12 | jar 13 | ${project.groupId}::${project.artifactId} 14 | 15 | 16 | ${project.basedir}/../LICENSE.md 17 | 18 | 19 | 20 | 21 | 22 | ${project.groupId} 23 | vmvm 24 | 25 | 26 | 27 | junit 28 | junit 29 | 30 | 31 | 32 | ant 33 | ant 34 | 35 | 36 | 37 | org.apache.ant 38 | ant-junit 39 | 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/src/main/java/edu/columbia/cs/psl/vmvm/AntJUnitTestListener.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm; 2 | 3 | import java.io.OutputStream; 4 | 5 | import junit.framework.AssertionFailedError; 6 | import junit.framework.Test; 7 | 8 | import org.apache.tools.ant.BuildException; 9 | import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; 10 | import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; 11 | 12 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 13 | 14 | public class AntJUnitTestListener implements JUnitResultFormatter { 15 | 16 | @Override 17 | public void endTestSuite(JUnitTest arg0) throws BuildException { 18 | Reinitializer.markAllClassesForReinit(); 19 | } 20 | 21 | @Override 22 | public void setOutput(OutputStream arg0) { 23 | // TODO Auto-generated method stub 24 | 25 | } 26 | 27 | @Override 28 | public void setSystemError(String arg0) { 29 | // TODO Auto-generated method stub 30 | 31 | } 32 | 33 | @Override 34 | public void setSystemOutput(String arg0) { 35 | // TODO Auto-generated method stub 36 | 37 | } 38 | 39 | @Override 40 | public void startTestSuite(JUnitTest arg0) throws BuildException { 41 | } 42 | 43 | @Override 44 | public void addError(Test arg0, Throwable arg1) { 45 | // TODO Auto-generated method stub 46 | 47 | } 48 | 49 | @Override 50 | public void addFailure(Test arg0, AssertionFailedError arg1) { 51 | // TODO Auto-generated method stub 52 | 53 | } 54 | 55 | @Override 56 | public void endTest(Test arg0) { 57 | // TODO Auto-generated method stub 58 | } 59 | 60 | @Override 61 | public void startTest(Test arg0) { 62 | // TODO Auto-generated method stub 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/src/main/java/edu/columbia/cs/psl/vmvm/MvnReportingListener.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.sql.Connection; 6 | import java.sql.DriverManager; 7 | import java.sql.PreparedStatement; 8 | import java.sql.SQLException; 9 | import java.util.Arrays; 10 | import java.util.Scanner; 11 | 12 | import org.junit.runner.Description; 13 | import org.junit.runner.Result; 14 | import org.junit.runner.notification.Failure; 15 | import org.junit.runner.notification.RunListener; 16 | 17 | import edu.columbia.cs.psl.vmvm.TestReportingListener.TestResult; 18 | 19 | public class MvnReportingListener extends RunListener { 20 | static final Connection db = getConnection(); 21 | static int testID; 22 | static { 23 | try { 24 | testID = Integer.valueOf(System.getProperty("vmvm.study.testID")); 25 | } catch (NumberFormatException ex) { 26 | Scanner s; 27 | try { 28 | s = new Scanner(new File("vmvm.study.testID")); 29 | testID = s.nextInt(); 30 | s.close(); 31 | } catch (FileNotFoundException e) { 32 | throw new IllegalStateException("No test id set!", e); 33 | } 34 | 35 | } 36 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 37 | 38 | @Override 39 | public void run() { 40 | try { 41 | db.close(); 42 | } catch (SQLException e) { 43 | // TODO Auto-generated catch block 44 | e.printStackTrace(); 45 | } 46 | } 47 | })); 48 | } 49 | 50 | static Connection getConnection() { 51 | try { 52 | Class.forName("com.mysql.jdbc.Driver"); 53 | return DriverManager.getConnection("jdbc:mysql://127.0.0.1/foss?user=foss&password=f055"); 54 | } catch (Exception ex) { 55 | ex.printStackTrace(); 56 | } 57 | return null; 58 | } 59 | 60 | private String getClassName(Description desc) 61 | { 62 | if(desc == null) 63 | return "null"; 64 | if(desc.getClassName() == null) 65 | return desc.getTestClass().getName(); 66 | else 67 | return desc.getClassName(); 68 | } 69 | int nFailures; 70 | String lastTestClass = null; 71 | @Override 72 | public void testRunStarted(Description description) throws Exception { 73 | if (!getClassName(description).equals(lastTestClass)) { 74 | //we are doing another test class 75 | if (res != null) 76 | finishedClass(); 77 | res = new TestResult(getClassName(description)); 78 | lastTestClass = getClassName(description); 79 | if(description.getChildren() != null && description.getChildren().size() == 1) 80 | { 81 | Description child = description.getChildren().get(0); 82 | long time = Long.valueOf(child.getDisplayName()); 83 | res.startTime = time; 84 | } 85 | } 86 | } 87 | /** 88 | * Called when an atomic test is about to be started. 89 | * */ 90 | public void testStarted(Description description) throws java.lang.Exception { 91 | if (!getClassName(description).equals(lastTestClass)) { 92 | //we are doing another test class 93 | if (res != null) 94 | finishedClass(); 95 | res = new TestResult(getClassName(description)); 96 | lastTestClass = getClassName(description); 97 | } 98 | if(res.startTime == 0 && description.getChildren() != null && description.getChildren().size() == 1) 99 | { 100 | Description child = description.getChildren().get(0); 101 | long time = Long.valueOf(child.getDisplayName()); 102 | res.startTime = time; 103 | 104 | } 105 | res.nMethods++; 106 | } 107 | 108 | @Override 109 | public void testFinished(Description description) throws Exception { 110 | res.stdout.append(description.getDisplayName() + "Finished\n"); 111 | if(description.getChildren() != null && description.getChildren().size() == 1) 112 | { 113 | Description child = description.getChildren().get(0); 114 | long time = Long.valueOf(child.getDisplayName()); 115 | res.finished = time; 116 | } 117 | } 118 | 119 | int nErrors; 120 | 121 | String lastFinishedClass = null; 122 | @Override 123 | public void testRunFinished(Result result) throws Exception { 124 | 125 | nFailures = result.getFailureCount(); 126 | if(!lastTestClass.equals(lastFinishedClass)) 127 | finishedClass(); 128 | lastFinishedClass = lastTestClass; 129 | } 130 | 131 | private void finishedClass() { 132 | if(res.reported) 133 | return; 134 | res.reported = true; 135 | if(res.finished == 0) 136 | res.finished = System.currentTimeMillis(); 137 | if(res.startTime == 0 && res.nMethods == 0) 138 | res.startTime = res.finished; 139 | try { 140 | PreparedStatement ps = db.prepareStatement("INSERT INTO test_result_test (test_execution_id,test,time,output,success,nTestMethods,start,end,nFailures) VALUES (?,?,?,?,?,?,?,?,?)"); 141 | ps.setInt(1, testID); 142 | ps.setString(2, res.name); 143 | ps.setLong(3, (int) (res.finished - res.startTime)); 144 | ps.setString(4, "Stdout:\n" + res.stdout.toString() + "\n\nStderr:\n" + res.stderr.toString()); 145 | ps.setInt(5, nFailures > 0 ? 0 : 1); 146 | ps.setInt(6, res.nMethods); 147 | ps.setLong(7, res.startTime); 148 | ps.setLong(8, res.finished); 149 | ps.setInt(9, nFailures); 150 | ps.executeUpdate(); 151 | } catch (SQLException ex) { 152 | ex.printStackTrace(); 153 | } 154 | 155 | } 156 | 157 | /** 158 | * Called when an atomic test fails. 159 | * */ 160 | public void testFailure(Failure failure) throws java.lang.Exception { 161 | nFailures++; 162 | res.failed = true; 163 | res.stderr.append("Failed on " + failure.getTestHeader() + ": " + failure.getMessage() + Arrays.toString(failure.getException().getStackTrace())); 164 | } 165 | 166 | public void testAssumptionFailure(Failure failure) { 167 | nFailures++; 168 | res.failed = true; 169 | res.stderr.append("Failed on " + failure.getTestHeader() + ": " + failure.getMessage() + Arrays.toString(failure.getException().getStackTrace())); 170 | } 171 | TestResult res; 172 | 173 | /** 174 | * Called when a test will not be run, generally because a test method is 175 | * annotated with Ignore. 176 | * */ 177 | public void testIgnored(Description description) throws java.lang.Exception { 178 | System.out.println("Execution of test case ignored : " + description.getMethodName()); 179 | } 180 | 181 | class TestResult { 182 | public long endTime; 183 | StringBuffer stdout = new StringBuffer(); 184 | StringBuffer stderr = new StringBuffer(); 185 | int nMethods = 0; 186 | long startTime = System.currentTimeMillis(); 187 | long finished; 188 | boolean failed; 189 | String name; 190 | boolean reported; 191 | 192 | public TestResult(String name) { 193 | this.name = name; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/src/main/java/edu/columbia/cs/psl/vmvm/MvnVMVMListener.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm; 2 | 3 | import org.junit.runner.Description; 4 | import org.junit.runner.notification.RunListener; 5 | 6 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 7 | 8 | public class MvnVMVMListener extends RunListener { 9 | 10 | @Override 11 | public void testStarted(Description description) throws Exception { 12 | Reinitializer.newTestClassHit(description.getClassName()); 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vmvm-ant-junit-formatter/src/main/java/edu/columbia/cs/psl/vmvm/TestReportingListener.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.OutputStream; 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.sql.Statement; 12 | import java.util.Arrays; 13 | import java.util.LinkedList; 14 | import java.util.Scanner; 15 | 16 | import junit.framework.AssertionFailedError; 17 | import junit.framework.Test; 18 | 19 | import org.apache.tools.ant.BuildException; 20 | import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; 21 | import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; 22 | 23 | 24 | public class TestReportingListener implements JUnitResultFormatter { 25 | 26 | static Connection db = getConnection(); 27 | static int testID; 28 | 29 | static 30 | { 31 | try{ 32 | testID = Integer.valueOf(System.getProperty("vmvm.study.testID")); 33 | } 34 | catch(NumberFormatException ex) 35 | { 36 | Scanner s; 37 | try { 38 | s = new Scanner(new File("vmvm.study.testID")); 39 | testID = s.nextInt(); 40 | s.close(); 41 | } catch (FileNotFoundException e) { 42 | throw new IllegalStateException("No test id set!", e); 43 | } 44 | 45 | } 46 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 47 | 48 | @Override 49 | public void run() { 50 | try { 51 | db.close(); 52 | } catch (SQLException e) { 53 | // TODO Auto-generated catch block 54 | e.printStackTrace(); 55 | } 56 | } 57 | })); 58 | } 59 | static Connection getConnection() { 60 | try { 61 | Class.forName("com.mysql.jdbc.Driver"); 62 | return DriverManager.getConnection("jdbc:mysql://127.0.0.1/foss?user=foss&password=f055"); 63 | } catch (Exception ex) { 64 | ex.printStackTrace(); 65 | } 66 | return null; 67 | } 68 | int nFailures; 69 | @Override 70 | public void addError(Test arg0, Throwable arg1) { 71 | nErrors++; 72 | res.failed = true; 73 | res.stderr.append("Failed on "+arg0+": " + arg1.getMessage()+Arrays.toString(arg1.getStackTrace())); 74 | } 75 | TestResult res; 76 | @Override 77 | public void addFailure(Test arg0, AssertionFailedError arg1) { 78 | { 79 | nFailures++; 80 | res.failed = true; 81 | res.stderr.append("Failed: " + arg1.getMessage()); 82 | } 83 | } 84 | 85 | @Override 86 | public void endTest(Test arg0) { 87 | 88 | } 89 | 90 | @Override 91 | public void startTest(Test arg0) { 92 | res.nMethods++; 93 | } 94 | static int nErrors; 95 | static boolean done = false; 96 | @Override 97 | public void endTestSuite(JUnitTest arg0) throws BuildException { 98 | res.finished = System.currentTimeMillis(); 99 | if(done) 100 | return; 101 | done = true; 102 | try{ 103 | if(db == null) 104 | db =getConnection(); 105 | PreparedStatement ps = db.prepareStatement("INSERT INTO test_result_test (test_execution_id,test,time,output,success,nTestMethods,start,end,nFailures,nErrors) VALUES (?,?,?,?,?,?,?,?,?,?)"); 106 | ps.setInt(1, testID); 107 | ps.setString(2, res.name); 108 | ps.setLong(3, arg0.getRunTime()); 109 | ps.setString(4, "Stdout:\n"+res.stdout.toString()+"\n\nStderr:\n"+res.stderr.toString()); 110 | ps.setInt(5, nFailures>0?0:1); 111 | ps.setInt(6, res.nMethods); 112 | ps.setLong(7, res.startTime); 113 | ps.setLong(8,res.finished); 114 | ps.setInt(9, nFailures); 115 | ps.setInt(10,nErrors); 116 | ps.executeUpdate(); 117 | } 118 | catch(SQLException ex) 119 | { 120 | ex.printStackTrace(); 121 | } 122 | } 123 | 124 | @Override 125 | public void setOutput(OutputStream arg0) { 126 | // TODO Auto-generated method stub 127 | 128 | } 129 | 130 | @Override 131 | public void setSystemError(String arg0) { 132 | res.stderr.append(arg0); 133 | } 134 | 135 | @Override 136 | public void setSystemOutput(String arg0) { 137 | res.stdout.append(arg0); 138 | } 139 | 140 | @Override 141 | public void startTestSuite(JUnitTest arg0) throws BuildException { 142 | done = false; 143 | nFailures=0; 144 | nErrors=0; 145 | res = (new TestResult(arg0.getName())); 146 | if(arg0.getProperties() == null || arg0.getProperties().getProperty("workerStartTime") == null) 147 | res.startTime = System.currentTimeMillis(); 148 | else 149 | res.startTime = Long.valueOf(arg0.getProperties().getProperty("workerStartTime")); 150 | } 151 | 152 | class TestResult 153 | { 154 | StringBuffer stdout = new StringBuffer(); 155 | StringBuffer stderr = new StringBuffer(); 156 | int nMethods=0; 157 | long startTime = System.currentTimeMillis(); 158 | long finished; 159 | boolean failed; 160 | String name; 161 | public TestResult(String name) 162 | { 163 | this.name=name; 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /vmvm-internal-static-detector/bin/log4j.properties: -------------------------------------------------------------------------------- 1 | 2 | log4j.rootCategory=INFO, stderr, file 3 | 4 | # Pattern to output the caller's file name and line number. 5 | log4j.appender.stderr=org.apache.log4j.ConsoleAppender 6 | log4j.appender.stderr.target=System.err 7 | log4j.appender.stderr.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.stderr.layout.ConversionPattern=[sd %d{HH:mm:ss}] %p [%t] %C{1}.%M(%L) | %m%n 9 | 10 | #[native-detector %d] %p [%t] %C.%M(%L) | %m%n 11 | 12 | log4j.appender.file=org.apache.log4j.RollingFileAppender 13 | log4j.appender.file.File=native-detector.log 14 | log4j.appender.file.MaxFileSize=100000KB 15 | log4j.appender.file.MaxBackupIndex=10 16 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 17 | log4j.appender.file.layout.ConversionPattern=[sd %d{HH:mm:ss}] %p [%t] %C{1}.%M(%L) | %m%n 18 | -------------------------------------------------------------------------------- /vmvm-internal-static-detector/lib/asm-all-4.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Programming-Systems-Lab/vmvm/07a36dc21373147c50ceacd7bff2b2e7a86c8780/vmvm-internal-static-detector/lib/asm-all-4.0.jar -------------------------------------------------------------------------------- /vmvm-internal-static-detector/lib/asm-src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Programming-Systems-Lab/vmvm/07a36dc21373147c50ceacd7bff2b2e7a86c8780/vmvm-internal-static-detector/lib/asm-src.zip -------------------------------------------------------------------------------- /vmvm-internal-static-detector/lib/log4j-1.2.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Programming-Systems-Lab/vmvm/07a36dc21373147c50ceacd7bff2b2e7a86c8780/vmvm-internal-static-detector/lib/log4j-1.2.16.jar -------------------------------------------------------------------------------- /vmvm-internal-static-detector/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | edu.gmu.swe.vmvm 6 | vmvm-base-pom 7 | 2.0.0-SNAPSHOT 8 | 9 | 10 | 4.0.0 11 | vmvm-internal-static-detector 12 | jar 13 | ${project.groupId}::${project.artifactId} 14 | 15 | 16 | ${project.basedir}/../LICENSE.md 17 | 18 | 19 | 20 | 21 | 22 | ${project.groupId} 23 | vmvm 24 | 25 | 26 | 27 | log4j 28 | log4j 29 | 30 | 31 | 32 | org.ow2.asm 33 | asm-all 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /vmvm-internal-static-detector/src/main/java/edu/columbia/cs/psl/vmvm/util/StaticPutDetector.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.util; 2 | 3 | import java.io.File; 4 | import java.io.FileWriter; 5 | import java.io.IOException; 6 | import java.util.Enumeration; 7 | import java.util.HashSet; 8 | import java.util.jar.JarEntry; 9 | import java.util.jar.JarFile; 10 | 11 | import org.apache.log4j.Logger; 12 | import org.objectweb.asm.ClassReader; 13 | import org.objectweb.asm.ClassVisitor; 14 | import org.objectweb.asm.ClassWriter; 15 | import org.objectweb.asm.MethodVisitor; 16 | import org.objectweb.asm.Opcodes; 17 | 18 | import edu.columbia.cs.psl.vmvm.Instrumenter; 19 | import edu.columbia.cs.psl.vmvm.asm.struct.MethodListClassNode; 20 | 21 | 22 | public class StaticPutDetector { 23 | private static final Logger logger = Logger.getLogger(StaticPutDetector.class); 24 | private static FileWriter fw; 25 | public static void main(String[] args) throws Throwable { 26 | File f = new File("static-mod-methods.txt"); 27 | if (f.exists()) 28 | f.delete(); 29 | // fw = new FileWriter(f); 30 | Instrumenter.pass_number = 0; 31 | Instrumenter.MAX_CLASSES = Integer.valueOf(args[1]); 32 | long start = System.currentTimeMillis(); 33 | Instrumenter.processJar(new File(args[0]),null); 34 | Instrumenter.finishedPass(); 35 | long end = System.currentTimeMillis(); 36 | System.err.println(Instrumenter.classesInstrumented +"\t"+(end-start)); 37 | // for(MethodListClassNode cn : Instrumenter.instrumentedClasses.values()) 38 | // { 39 | // if(cn.clInitCalculatedNecessary && (cn.name.startsWith("java") || cn.name.startsWith("System"))) 40 | // { 41 | // System.err.println(cn.name); 42 | // } 43 | // } 44 | // fw.close(); 45 | // findAllStatics("/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar"); 46 | } 47 | private static void findAllStatics(String path) 48 | { 49 | JarFile classJar; 50 | try { 51 | classJar = new JarFile(path); 52 | 53 | Enumeration jarContents = classJar.entries(); 54 | int i = 0; 55 | while (jarContents.hasMoreElements()) { 56 | String name = jarContents.nextElement().getName(); 57 | if (!name.endsWith(".class")) 58 | continue; 59 | name = name.substring(0, name.length() - 6); 60 | try{ 61 | ClassReader cr = new ClassReader(name); 62 | StaticFinderCV ccv = new StaticFinderCV(Opcodes.ASM4) 63 | ; cr.accept(ccv, 0); 64 | } 65 | catch(IOException ex) 66 | { 67 | System.out.println(name); 68 | ex.printStackTrace(); 69 | } 70 | i++; 71 | if (i % 5000 == 0) 72 | logger.info(i + " classes processed"); 73 | } 74 | classJar.close(); 75 | } catch (IOException e) { 76 | // TODO Auto-generated catch block 77 | e.printStackTrace(); 78 | } 79 | 80 | } 81 | static class StaticFinderCV extends ClassVisitor{ 82 | private String className; 83 | public StaticFinderCV(int api) { 84 | super(api); 85 | } 86 | @Override 87 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 88 | this.className = name; 89 | } 90 | @Override 91 | public void visitEnd() { 92 | if(isBad && className.startsWith("java") && (sets.size() >0 || adds.size() >0)) 93 | System.err.println(className + adds + "." + removes + "."+sets+"."+gets); 94 | super.visitEnd(); 95 | } 96 | private boolean isBad = false; 97 | private HashSet adds = new HashSet(); 98 | private HashSet sets = new HashSet(); 99 | private HashSet gets = new HashSet(); 100 | private HashSet removes = new HashSet(); 101 | @Override 102 | public MethodVisitor visitMethod(int access, final String methodName, final String methodDesc, String signature, String[] exceptions) { 103 | if((access & Opcodes.ACC_STATIC) != 0 && (methodName.startsWith("set") || methodName.startsWith("add") || methodName.startsWith("remove") || methodName.startsWith("get"))) 104 | { 105 | if((access & Opcodes.ACC_PUBLIC) == 0) 106 | return null; 107 | if(methodName.startsWith("add")) 108 | adds.add(methodName); 109 | if(methodName.startsWith("remove")) 110 | removes.add(methodName); 111 | if(methodName.startsWith("set")) 112 | sets.add(methodName); 113 | if(methodName.startsWith("get")) 114 | gets.add(methodName); 115 | 116 | isBad = true; 117 | } 118 | return null; 119 | } 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /vmvm-internal-static-detector/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | 2 | log4j.rootCategory=INFO, stderr, file 3 | 4 | # Pattern to output the caller's file name and line number. 5 | log4j.appender.stderr=org.apache.log4j.ConsoleAppender 6 | log4j.appender.stderr.target=System.err 7 | log4j.appender.stderr.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.stderr.layout.ConversionPattern=[sd %d{HH:mm:ss}] %p [%t] %C{1}.%M(%L) | %m%n 9 | 10 | #[native-detector %d] %p [%t] %C.%M(%L) | %m%n 11 | 12 | log4j.appender.file=org.apache.log4j.RollingFileAppender 13 | log4j.appender.file.File=native-detector.log 14 | log4j.appender.file.MaxFileSize=100000KB 15 | log4j.appender.file.MaxBackupIndex=10 16 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 17 | log4j.appender.file.layout.ConversionPattern=[sd %d{HH:mm:ss}] %p [%t] %C{1}.%M(%L) | %m%n 18 | -------------------------------------------------------------------------------- /vmvm-internal-static-detector/vmvm-internal-static-detector.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /vmvm/.gitignore: -------------------------------------------------------------------------------- 1 | debug 2 | dependency-reduced-pom.xml 3 | .classpath 4 | .settings 5 | .project 6 | target 7 | .cproject 8 | -------------------------------------------------------------------------------- /vmvm/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | edu.gmu.swe.vmvm 6 | vmvm-base-pom 7 | 2.0.0-SNAPSHOT 8 | 9 | 10 | 4.0.0 11 | vmvm 12 | jar 13 | ${project.groupId}::${project.artifactId} 14 | 15 | ${project.basedir}/../LICENSE.md 16 | edu.columbia.cs.psl.vmvm.runtime.PreMain 17 | ${premain.class.name} 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-jar-plugin 25 | true 26 | 27 | 28 | 29 | true 30 | true 31 | true 32 | ${main.class.name} 33 | 34 | 35 | ${buildNumber} 36 | ${premain.class.name} 37 | ${agent.class.name} 38 | true 39 | true 40 | 41 | 42 | 43 | 44 | 45 | jar 46 | 47 | jar 48 | 49 | 50 | 51 | 52 | 53 | maven-compiler-plugin 54 | 3.1 55 | 56 | 1.8 57 | 1.8 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-failsafe-plugin 63 | 2.18.1 64 | 65 | 66 | 67 | integration-test 68 | verify 69 | 70 | 71 | 72 | 73 | -Xbootclasspath/p:${project.build.directory}/${project.build.finalName}.jar 74 | 75 | -javaagent:${project.build.directory}/${project.build.finalName}.jar 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-shade-plugin 81 | 2.3 82 | 83 | 84 | package 85 | 86 | shade 87 | 88 | 89 | 90 | 91 | org.apache.commons.cli 92 | edu.columbia.cs.psl.vmvm.org.apache.commons.cli 93 | 94 | 95 | org.objectweb.asm 96 | edu.columbia.cs.psl.vmvm.org.objectweb.asm 97 | 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | junit 110 | junit 111 | 4.11 112 | test 113 | 114 | 115 | commons-cli 116 | commons-cli 117 | 1.2 118 | 119 | 120 | org.ow2.asm 121 | asm-all 122 | 5.0.3 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/AdditionalInterfaceClassloader.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import java.util.HashMap; 4 | 5 | public class AdditionalInterfaceClassloader extends ClassLoader { 6 | HashMap definedClasses = new HashMap(); 7 | 8 | public void addClass(String name, byte[] b) { 9 | definedClasses.put(name, b); 10 | } 11 | 12 | protected java.lang.Class findClass(String name) throws ClassNotFoundException { 13 | if (definedClasses.containsKey(name)) { 14 | byte[] b = definedClasses.remove(name); 15 | Class c = defineClass(name, b, 0, b.length); 16 | resolveClass(c); 17 | return c; 18 | } 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/ConsumerUtils.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import edu.columbia.cs.psl.vmvm.runtime.inst.Utils; 4 | 5 | public class ConsumerUtils { 6 | public boolean isIgnoredClass(String internalName) { 7 | return Utils.ignorePattern != null && internalName.startsWith(Utils.ignorePattern); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/FieldReflectionWrapper.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import java.edu.columbia.cs.psl.vmvm.runtime.ReflectionWrapper; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Modifier; 6 | 7 | public class FieldReflectionWrapper { 8 | 9 | public static Field tryToInit(Field f, Object obj) 10 | { 11 | if (Modifier.isStatic(f.getModifiers())) 12 | ReflectionWrapper.tryToInit(f.getDeclaringClass()); 13 | return f; 14 | } 15 | 16 | public static Field tryToInit(Field f) throws IllegalArgumentException, IllegalAccessException { 17 | if (Modifier.isStatic(f.getModifiers())) 18 | ReflectionWrapper.tryToInit(f.getDeclaringClass()); 19 | return f; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/Instrumenter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.nio.channels.FileChannel; 11 | import java.util.Enumeration; 12 | import java.util.Scanner; 13 | import java.util.jar.JarEntry; 14 | import java.util.jar.JarFile; 15 | import java.util.jar.JarOutputStream; 16 | import java.util.zip.ZipEntry; 17 | import java.util.zip.ZipException; 18 | import java.util.zip.ZipFile; 19 | import java.util.zip.ZipOutputStream; 20 | 21 | import org.apache.commons.cli.BasicParser; 22 | import org.apache.commons.cli.CommandLine; 23 | import org.apache.commons.cli.CommandLineParser; 24 | import org.apache.commons.cli.HelpFormatter; 25 | import org.apache.commons.cli.Option; 26 | import org.apache.commons.cli.Options; 27 | import org.objectweb.asm.ClassReader; 28 | import org.objectweb.asm.ClassWriter; 29 | import org.objectweb.asm.util.CheckClassAdapter; 30 | 31 | public class Instrumenter { 32 | public static ClassLoader loader; 33 | 34 | static String curPath; 35 | 36 | static int n = 0; 37 | 38 | public static byte[] instrumentClass(String name, InputStream is, boolean renameInterfaces) { 39 | try { 40 | n++; 41 | if (n % 1000 == 0) 42 | System.out.println("Processed: " + n); 43 | curPath = name; 44 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 45 | 46 | int nRead; 47 | byte[] data = new byte[16384]; 48 | 49 | while ((nRead = is.read(data, 0, data.length)) != -1) { 50 | buffer.write(data, 0, nRead); 51 | } 52 | 53 | buffer.flush(); 54 | VMVMClassFileTransformer transformer = new VMVMClassFileTransformer(); 55 | ClassReader cr = new ClassReader(buffer.toByteArray()); 56 | 57 | byte[] ret = transformer.transform(Instrumenter.loader, cr.getClassName(), null, null, buffer.toByteArray()); 58 | curPath = null; 59 | return ret; 60 | } catch (Exception ex) { 61 | curPath = null; 62 | ex.printStackTrace(); 63 | return null; 64 | } 65 | } 66 | 67 | static Option help = new Option("help", "print this message"); 68 | 69 | public static void main(String[] args) { 70 | 71 | Options options = new Options(); 72 | options.addOption(help); 73 | 74 | CommandLineParser parser = new BasicParser(); 75 | CommandLine line = null; 76 | try { 77 | line = parser.parse(options, args); 78 | } catch (org.apache.commons.cli.ParseException exp) { 79 | 80 | HelpFormatter formatter = new HelpFormatter(); 81 | formatter.printHelp("java -jar instrumenter.jar [OPTIONS] [input] [output]", options); 82 | System.err.println(exp.getMessage()); 83 | return; 84 | } 85 | if (line.hasOption("help") || line.getArgs().length != 2) { 86 | HelpFormatter formatter = new HelpFormatter(); 87 | formatter.printHelp("java -jar instrumenter.jar [OPTIONS] [input] [output]", options); 88 | return; 89 | } 90 | 91 | PreMain.IS_RUNTIME_INST = false; 92 | instrumentDir(line.getArgs()[0], line.getArgs()[1]); 93 | } 94 | 95 | static File rootOutputDir; 96 | 97 | public static void instrumentDir(String inputFolder, String outputFolder) { 98 | 99 | rootOutputDir = new File(outputFolder); 100 | if (!rootOutputDir.exists()) 101 | rootOutputDir.mkdir(); 102 | File f = new File(inputFolder); 103 | if (!f.exists()) { 104 | System.err.println("Unable to read path " + inputFolder); 105 | System.exit(-1); 106 | } 107 | if (f.isDirectory()) 108 | processDirectory(f, rootOutputDir, true); 109 | else if (inputFolder.endsWith(".jar") || inputFolder.endsWith(".war")) 110 | processJar(f, rootOutputDir); 111 | else if (inputFolder.endsWith(".class")) 112 | try { 113 | processClass(f.getName(), new FileInputStream(f), rootOutputDir); 114 | } catch (FileNotFoundException e) { 115 | e.printStackTrace(); 116 | } 117 | else if (inputFolder.endsWith(".zip")) { 118 | processZip(f, rootOutputDir); 119 | } else { 120 | System.err.println("Unknown type for path " + inputFolder); 121 | System.exit(-1); 122 | } 123 | } 124 | 125 | static String lastInstrumentedClass; 126 | 127 | private static void processClass(String name, InputStream is, File outputDir) { 128 | 129 | try { 130 | FileOutputStream fos = new FileOutputStream(outputDir.getPath() + File.separator + name); 131 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 132 | lastInstrumentedClass = outputDir.getPath() + File.separator + name; 133 | 134 | byte[] c = instrumentClass(outputDir.getAbsolutePath(), is, true); 135 | bos.write(c); 136 | bos.writeTo(fos); 137 | fos.close(); 138 | is.close(); 139 | 140 | } catch (Exception ex) { 141 | ex.printStackTrace(); 142 | } 143 | } 144 | 145 | private static void processDirectory(File f, File parentOutputDir, boolean isFirstLevel) { 146 | File thisOutputDir; 147 | if (isFirstLevel) { 148 | thisOutputDir = parentOutputDir; 149 | } else { 150 | thisOutputDir = new File(parentOutputDir.getAbsolutePath() + File.separator + f.getName()); 151 | thisOutputDir.mkdir(); 152 | } 153 | for (File fi : f.listFiles()) { 154 | if (fi.isDirectory()) 155 | processDirectory(fi, thisOutputDir, false); 156 | else if (fi.getName().endsWith(".class")) 157 | try { 158 | processClass(fi.getName(), new FileInputStream(fi), thisOutputDir); 159 | } catch (FileNotFoundException e) { 160 | e.printStackTrace(); 161 | } 162 | else if (fi.getName().endsWith(".jar") || fi.getName().endsWith(".war")) 163 | processJar(fi, thisOutputDir); 164 | else if (fi.getName().endsWith(".zip")) 165 | processZip(fi, thisOutputDir); 166 | else { 167 | File dest = new File(thisOutputDir.getPath() + File.separator + fi.getName()); 168 | FileChannel source = null; 169 | FileChannel destination = null; 170 | 171 | try { 172 | source = new FileInputStream(fi).getChannel(); 173 | destination = new FileOutputStream(dest).getChannel(); 174 | destination.transferFrom(source, 0, source.size()); 175 | } catch (Exception ex) { 176 | System.err.println("error copying file " + fi); 177 | ex.printStackTrace(); 178 | } finally { 179 | if (source != null) { 180 | try { 181 | source.close(); 182 | } catch (IOException e) { 183 | e.printStackTrace(); 184 | } 185 | } 186 | if (destination != null) { 187 | try { 188 | destination.close(); 189 | } catch (IOException e) { 190 | e.printStackTrace(); 191 | } 192 | } 193 | } 194 | 195 | } 196 | } 197 | 198 | } 199 | 200 | public static void processJar(File f, File outputDir) { 201 | try { 202 | JarFile jar = new JarFile(f); 203 | JarOutputStream jos = null; 204 | jos = new JarOutputStream(new FileOutputStream(outputDir.getPath() + File.separator + f.getName())); 205 | Enumeration entries = jar.entries(); 206 | while (entries.hasMoreElements()) { 207 | JarEntry e = entries.nextElement(); 208 | if (e.getName().endsWith(".class")) { 209 | { 210 | 211 | try { 212 | JarEntry outEntry = new JarEntry(e.getName()); 213 | jos.putNextEntry(outEntry); 214 | byte[] clazz = instrumentClass(f.getAbsolutePath(), jar.getInputStream(e), true); 215 | if (clazz == null) { 216 | System.out.println("Failed to instrument " + e.getName() + " in " + f.getName()); 217 | InputStream is = jar.getInputStream(e); 218 | byte[] buffer = new byte[1024]; 219 | while (true) { 220 | int count = is.read(buffer); 221 | if (count == -1) 222 | break; 223 | jos.write(buffer, 0, count); 224 | } 225 | } else { 226 | jos.write(clazz); 227 | } 228 | jos.closeEntry(); 229 | } catch (ZipException ex) { 230 | ex.printStackTrace(); 231 | continue; 232 | } 233 | 234 | } 235 | 236 | } else { 237 | JarEntry outEntry = new JarEntry(e.getName()); 238 | if (e.isDirectory()) { 239 | try { 240 | jos.putNextEntry(outEntry); 241 | jos.closeEntry(); 242 | } catch (ZipException exxx) { 243 | System.out.println("Ignoring exception: " + exxx); 244 | } 245 | } else if (e.getName().startsWith("META-INF") && (e.getName().endsWith(".SF") || e.getName().endsWith(".RSA"))) { 246 | // don't copy this 247 | } else if (e.getName().equals("META-INF/MANIFEST.MF")) { 248 | Scanner s = new Scanner(jar.getInputStream(e)); 249 | jos.putNextEntry(outEntry); 250 | 251 | String curPair = ""; 252 | while (s.hasNextLine()) { 253 | String line = s.nextLine(); 254 | if (line.equals("")) { 255 | curPair += "\n"; 256 | if (!curPair.contains("SHA1-Digest:")) 257 | jos.write(curPair.getBytes()); 258 | curPair = ""; 259 | } else { 260 | curPair += line + "\n"; 261 | } 262 | } 263 | s.close(); 264 | jos.closeEntry(); 265 | } else { 266 | try { 267 | jos.putNextEntry(outEntry); 268 | InputStream is = jar.getInputStream(e); 269 | byte[] buffer = new byte[1024]; 270 | while (true) { 271 | int count = is.read(buffer); 272 | if (count == -1) 273 | break; 274 | jos.write(buffer, 0, count); 275 | } 276 | jos.closeEntry(); 277 | } catch (ZipException ex) { 278 | if (!ex.getMessage().contains("duplicate entry")) { 279 | ex.printStackTrace(); 280 | System.out.println("Ignoring above warning from improper source zip..."); 281 | } 282 | } 283 | } 284 | 285 | } 286 | 287 | } 288 | if (jos != null) { 289 | jos.close(); 290 | 291 | } 292 | jar.close(); 293 | } catch (Exception e) { 294 | System.err.println("Unable to process jar: " + f.getAbsolutePath()); 295 | e.printStackTrace(); 296 | File dest = new File(outputDir.getPath() + File.separator + f.getName()); 297 | FileChannel source = null; 298 | FileChannel destination = null; 299 | 300 | try { 301 | source = new FileInputStream(f).getChannel(); 302 | destination = new FileOutputStream(dest).getChannel(); 303 | destination.transferFrom(source, 0, source.size()); 304 | } catch (Exception ex) { 305 | System.err.println("Unable to copy file: " + f.getAbsolutePath()); 306 | ex.printStackTrace(); 307 | } finally { 308 | if (source != null) { 309 | try { 310 | source.close(); 311 | } catch (IOException e2) { 312 | e2.printStackTrace(); 313 | } 314 | } 315 | if (destination != null) { 316 | try { 317 | destination.close(); 318 | } catch (IOException e2) { 319 | e2.printStackTrace(); 320 | } 321 | } 322 | } 323 | } 324 | 325 | } 326 | 327 | private static void processZip(File f, File outputDir) { 328 | try { 329 | ZipFile zip = new ZipFile(f); 330 | ZipOutputStream zos = null; 331 | zos = new ZipOutputStream(new FileOutputStream(outputDir.getPath() + File.separator + f.getName())); 332 | Enumeration entries = zip.entries(); 333 | while (entries.hasMoreElements()) { 334 | ZipEntry e = entries.nextElement(); 335 | 336 | if (e.getName().endsWith(".class")) { 337 | { 338 | ZipEntry outEntry = new ZipEntry(e.getName()); 339 | zos.putNextEntry(outEntry); 340 | 341 | byte[] clazz = instrumentClass(f.getAbsolutePath(), zip.getInputStream(e), true); 342 | if (clazz == null) { 343 | InputStream is = zip.getInputStream(e); 344 | byte[] buffer = new byte[1024]; 345 | while (true) { 346 | int count = is.read(buffer); 347 | if (count == -1) 348 | break; 349 | zos.write(buffer, 0, count); 350 | } 351 | } else 352 | zos.write(clazz); 353 | zos.closeEntry(); 354 | 355 | } 356 | 357 | } else if (e.getName().endsWith(".jar")) { 358 | ZipEntry outEntry = new ZipEntry(e.getName()); 359 | File tmp = new File("/tmp/classfile"); 360 | if (tmp.exists()) 361 | tmp.delete(); 362 | FileOutputStream fos = new FileOutputStream(tmp); 363 | byte buf[] = new byte[1024]; 364 | int len; 365 | InputStream is = zip.getInputStream(e); 366 | while ((len = is.read(buf)) > 0) { 367 | fos.write(buf, 0, len); 368 | } 369 | is.close(); 370 | fos.close(); 371 | 372 | File tmp2 = new File("tmp2"); 373 | if (!tmp2.exists()) 374 | tmp2.mkdir(); 375 | processJar(tmp, new File("tmp2")); 376 | 377 | zos.putNextEntry(outEntry); 378 | is = new FileInputStream("tmp2/classfile"); 379 | byte[] buffer = new byte[1024]; 380 | while (true) { 381 | int count = is.read(buffer); 382 | if (count == -1) 383 | break; 384 | zos.write(buffer, 0, count); 385 | } 386 | is.close(); 387 | zos.closeEntry(); 388 | } else { 389 | ZipEntry outEntry = new ZipEntry(e.getName()); 390 | if (e.isDirectory()) { 391 | try { 392 | zos.putNextEntry(outEntry); 393 | zos.closeEntry(); 394 | } catch (ZipException exxxx) { 395 | System.out.println("Ignoring exception: " + exxxx.getMessage()); 396 | } 397 | } else if (e.getName().startsWith("META-INF") && (e.getName().endsWith(".SF") || e.getName().endsWith(".RSA"))) { 398 | // don't copy this 399 | } else if (e.getName().equals("META-INF/MANIFEST.MF")) { 400 | Scanner s = new Scanner(zip.getInputStream(e)); 401 | zos.putNextEntry(outEntry); 402 | 403 | String curPair = ""; 404 | while (s.hasNextLine()) { 405 | String line = s.nextLine(); 406 | if (line.equals("")) { 407 | curPair += "\n"; 408 | if (!curPair.contains("SHA1-Digest:")) 409 | zos.write(curPair.getBytes()); 410 | curPair = ""; 411 | } else { 412 | curPair += line + "\n"; 413 | } 414 | } 415 | s.close(); 416 | zos.write("\n".getBytes()); 417 | zos.closeEntry(); 418 | } else { 419 | zos.putNextEntry(outEntry); 420 | InputStream is = zip.getInputStream(e); 421 | byte[] buffer = new byte[1024]; 422 | while (true) { 423 | int count = is.read(buffer); 424 | if (count == -1) 425 | break; 426 | zos.write(buffer, 0, count); 427 | } 428 | zos.closeEntry(); 429 | } 430 | } 431 | 432 | } 433 | zos.close(); 434 | zip.close(); 435 | } catch (Exception e) { 436 | System.err.println("Unable to process zip: " + f.getAbsolutePath()); 437 | e.printStackTrace(); 438 | File dest = new File(outputDir.getPath() + File.separator + f.getName()); 439 | FileChannel source = null; 440 | FileChannel destination = null; 441 | 442 | try { 443 | source = new FileInputStream(f).getChannel(); 444 | destination = new FileOutputStream(dest).getChannel(); 445 | destination.transferFrom(source, 0, source.size()); 446 | } catch (Exception ex) { 447 | System.err.println("Unable to copy zip: " + f.getAbsolutePath()); 448 | ex.printStackTrace(); 449 | } finally { 450 | if (source != null) { 451 | try { 452 | source.close(); 453 | } catch (IOException e2) { 454 | e2.printStackTrace(); 455 | } 456 | } 457 | if (destination != null) { 458 | try { 459 | destination.close(); 460 | } catch (IOException e2) { 461 | e2.printStackTrace(); 462 | } 463 | } 464 | } 465 | } 466 | 467 | } 468 | 469 | } -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/JUnitInterceptingClassVisitor.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.Type; 7 | 8 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 9 | 10 | public class JUnitInterceptingClassVisitor extends ClassVisitor { 11 | /* 12 | org.junit.internal.requests.ClassRequest(Class, boolean) <-- here 13 | */ 14 | public JUnitInterceptingClassVisitor(ClassVisitor cv) { 15 | super(Opcodes.ASM5, cv); 16 | } 17 | 18 | @Override 19 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 20 | 21 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 22 | if (name.equals("") && desc.equals("(Ljava/lang/Class;Z)V")) { 23 | mv = new MethodVisitor(Opcodes.ASM5, mv) { 24 | boolean intercepted = false; 25 | 26 | @Override 27 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 28 | super.visitMethodInsn(opcode, owner, name, desc, itf); 29 | 30 | if (!intercepted && name.equals("")) { 31 | intercepted = true; 32 | super.visitVarInsn(Opcodes.ALOAD, 1); 33 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Reinitializer.class), "newTestClassHit", "(Ljava/lang/Class;)V", false); 34 | } 35 | } 36 | }; 37 | } 38 | return mv; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/PreMain.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import edu.columbia.cs.psl.vmvm.runtime.inst.Utils; 4 | 5 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 6 | import java.lang.instrument.Instrumentation; 7 | import java.lang.instrument.UnmodifiableClassException; 8 | 9 | public class PreMain { 10 | public static boolean IS_RUNTIME_INST = true; 11 | 12 | public static void premain(String args, Instrumentation inst) { 13 | Reinitializer.inst = inst; 14 | if(args != null) 15 | Utils.ignorePattern = args; 16 | for(Class c : inst.getAllLoadedClasses()){ 17 | VMVMClassFileTransformer.ignoredClasses.add(c.getName().replace('.','/')); 18 | } 19 | inst.addTransformer(new VMVMClassFileTransformer(), true); 20 | for(Class c : inst.getAllLoadedClasses()){ 21 | try { 22 | inst.retransformClasses(c); 23 | } catch (UnmodifiableClassException e) { 24 | } catch(Throwable t){ 25 | t.printStackTrace(); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/VMVMClassFileTransformer.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import java.edu.columbia.cs.psl.vmvm.runtime.InterfaceReinitializer; 4 | import java.edu.columbia.cs.psl.vmvm.runtime.VMVMInstrumented; 5 | import edu.columbia.cs.psl.vmvm.runtime.inst.ClassReinitCV; 6 | import edu.columbia.cs.psl.vmvm.runtime.inst.Constants; 7 | import edu.columbia.cs.psl.vmvm.runtime.inst.ReflectionFixingCV; 8 | import org.objectweb.asm.*; 9 | import org.objectweb.asm.tree.ClassNode; 10 | import org.objectweb.asm.tree.MethodNode; 11 | import org.objectweb.asm.util.CheckClassAdapter; 12 | import sun.misc.Unsafe; 13 | 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.io.IOException; 17 | import java.lang.instrument.ClassFileTransformer; 18 | import java.lang.instrument.IllegalClassFormatException; 19 | import java.lang.reflect.Field; 20 | import java.security.ProtectionDomain; 21 | import java.util.HashSet; 22 | 23 | public class VMVMClassFileTransformer implements ClassFileTransformer { 24 | 25 | public static HashSet ignoredClasses = new HashSet<>(); 26 | public static boolean isIgnoredClass(String internalName) { 27 | internalName = internalName.replace('.','/'); 28 | if (isWhitelistedClass(internalName)) 29 | return false; 30 | if(ignoredClasses.contains(internalName)) 31 | return true; 32 | return 33 | internalName.startsWith("java") 34 | || internalName.startsWith("jdk") 35 | || internalName.startsWith("sun/misc") 36 | || internalName.startsWith("sun/reflect") 37 | || internalName.equals("sun/java2d/opengl/OGLRenderQueue") 38 | || internalName.startsWith("sun") 39 | || internalName.startsWith("com/sun/java/util/jar") 40 | || internalName.startsWith("edu/columbia/cs/psl/vmvm/runtime") 41 | || internalName.startsWith("org/junit") 42 | || internalName.startsWith("junit/") 43 | || internalName.startsWith("java/edu/columbia/cs/psl/vmvm") 44 | || internalName.startsWith("edu/columbia/cs/psl/vmvm/") 45 | || internalName.startsWith("org/apache/maven/surefire") || internalName.startsWith("org/apache/tools/") 46 | || internalName.startsWith("org/mockito") || internalName.startsWith("mockit") 47 | || internalName.startsWith("org/powermock") 48 | || internalName.startsWith("com/jprofiler"); 49 | } 50 | 51 | public static boolean isWhitelistedClass(String internalName) { 52 | return internalName.startsWith("javax/servlet") || internalName.startsWith("com/sun/jini") || internalName.startsWith("java/awt") || internalName.startsWith("javax/swing") || internalName.startsWith("javax/xml") || internalName.startsWith("sun/awt"); 53 | } 54 | 55 | public static boolean isClassThatNeedsReflectionHacked(String internalName) { 56 | return ignoredClasses.contains(internalName) || internalName.startsWith("java/io/ObjectOutputStream") || internalName.startsWith("java/io/ObjectStream") 57 | || internalName.startsWith("sun/reflect/annotation/AnnotationInvocationHandler"); 58 | // return internalName.startsWith("java/") && !internalName.startsWith("java/lang/reflect") && !internalName.equals("java/lang/Class"); 59 | } 60 | 61 | public static AdditionalInterfaceClassloader cl = new AdditionalInterfaceClassloader(); 62 | 63 | public static HashSet instrumentedClasses = new HashSet(); 64 | public static final boolean DEBUG = System.getProperty("vmvm.debug") != null; 65 | public static final boolean ALWAYS_REOPT = false; 66 | public static final boolean HOTSPOT_REOPT = false; 67 | 68 | @SuppressWarnings("restriction") 69 | static sun.misc.Unsafe theUnsafe; 70 | 71 | @SuppressWarnings("restriction") 72 | public static sun.misc.Unsafe getUnsafe() { 73 | if (theUnsafe == null) { 74 | try { 75 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); 76 | f.setAccessible(true); 77 | theUnsafe = (Unsafe) f.get(null); 78 | }catch(NoSuchFieldException | IllegalAccessException ex){ 79 | ex.printStackTrace(); 80 | } 81 | } 82 | return theUnsafe; 83 | } 84 | 85 | public static Class generateResetter(Class hostClass) 86 | { 87 | 88 | String hostName = hostClass.getName().replace(".","/"); 89 | String newName = hostName + Constants.VMVM_RESET_FIELD; 90 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 91 | Integer version = ClassReinitCV.reClinitClassHelperVersions.remove(hostName); 92 | if(version == null) 93 | version = Opcodes.V1_8; 94 | cw.visit(version, Opcodes.ACC_PUBLIC, newName , null, InterfaceReinitializer.INTERNAL_NAME, null); 95 | cw.visitSource(null, null); 96 | MethodNode clinitMethod = ClassReinitCV.reClinitMethods.remove(hostName); 97 | if(clinitMethod != null) 98 | { 99 | cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;", null, null); 100 | clinitMethod.accept(cw); 101 | } 102 | else{ 103 | MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, "__vmvmReClinit", "()V", null, null); 104 | mv.visitCode(); 105 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, hostName, "__vmvmReClinit", "()V", false); 106 | mv.visitInsn(Opcodes.RETURN); 107 | mv.visitMaxs(0, 0); 108 | mv.visitEnd(); 109 | } 110 | MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); 111 | mv.visitCode(); 112 | mv.visitVarInsn(Opcodes.ALOAD, 0); 113 | mv.visitMethodInsn(Opcodes.INVOKESPECIAL, InterfaceReinitializer.INTERNAL_NAME, "", "()V", false); 114 | mv.visitInsn(Opcodes.RETURN); 115 | mv.visitMaxs(0, 0); 116 | mv.visitEnd(); 117 | cw.visitEnd(); 118 | byte[] b = cw.toByteArray(); 119 | if (DEBUG) { 120 | File debugDir = new File("debug"); 121 | if (!debugDir.exists()) 122 | debugDir.mkdir(); 123 | File f = new File("debug/" + newName.replace("/",".") +".class"); 124 | FileOutputStream fos = null; 125 | try { 126 | fos = new FileOutputStream(f); 127 | fos.write(cw.toByteArray()); 128 | fos.close(); 129 | } catch (IOException e) { 130 | e.printStackTrace(); 131 | } 132 | } 133 | if (DEBUG) { 134 | ClassReader cr2 = new ClassReader(b); 135 | cr2.accept(new CheckClassAdapter(new ClassWriter(0)), 0); 136 | } 137 | return getUnsafe().defineAnonymousClass(hostClass, b, new Object[0]); 138 | } 139 | private void generateResetter(ClassReader cr, ClassReinitCV cv, String className, ClassLoader loader, ProtectionDomain protectionDomain) { 140 | if ( 141 | ((instrumentedClasses.contains(className)) 142 | )) //|| hasClass(loader, className + Constants.VMVM_RESET_FIELD))) 143 | return; 144 | String newName = cr.getClassName() + Constants.VMVM_RESET_FIELD; 145 | // System.out.println("Generating " + newName); 146 | instrumentedClasses.add(className); 147 | 148 | try { 149 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 150 | cw.visitSource(null, null); 151 | 152 | 153 | 154 | cw.visitEnd(); 155 | if (DEBUG) { 156 | File debugDir = new File("debug"); 157 | if (!debugDir.exists()) 158 | debugDir.mkdir(); 159 | File f = new File("debug/" + newName.replace("/", ".") + ".class"); 160 | FileOutputStream fos = new FileOutputStream(f); 161 | fos.write(cw.toByteArray()); 162 | fos.close(); 163 | } 164 | byte[] b = cw.toByteArray(); 165 | if (DEBUG) { 166 | ClassReader cr2 = new ClassReader(b); 167 | cr2.accept(new CheckClassAdapter(new ClassWriter(0)), 0); 168 | } 169 | if(alwaysLoadInBootCP(newName)) 170 | { 171 | loader = null; 172 | protectionDomain = null; 173 | } 174 | // System.out.println("Done with " + newName + " in " + System.identityHashCode(loader) + ", " + System.identityHashCode(protectionDomain)); 175 | getUnsafe().defineClass(newName.replace("/", "."), b, 0, b.length, loader, protectionDomain); 176 | 177 | } catch (Exception ex) { 178 | System.err.println("Problem while creating " + newName); 179 | ex.printStackTrace(); 180 | 181 | System.exit(-1); 182 | } 183 | } 184 | 185 | private boolean alwaysLoadInBootCP(String newName) { 186 | return newName.startsWith("org/xml") 187 | || newName.startsWith("org/w3c") 188 | || newName.startsWith("java/") 189 | || newName.startsWith("javax/"); 190 | } 191 | 192 | private static HashSet instrumentedInterfaces = new HashSet(); 193 | 194 | @SuppressWarnings("restriction") 195 | @Override 196 | public synchronized byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 197 | // if(DEBUG) 198 | // System.err.println("VMVMClassfiletransformer PLAIN1 " + className + " " + loader + " " + classBeingRedefined); 199 | if(className == null) 200 | return null; 201 | if(className.equals("org/junit/internal/requests/ClassRequest")) 202 | { 203 | try { 204 | ClassReader cr = new ClassReader(classfileBuffer); 205 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 206 | JUnitInterceptingClassVisitor cv = new JUnitInterceptingClassVisitor(cw); 207 | cr.accept(cv, 0); 208 | if (DEBUG) { 209 | File debugDir = new File("debug"); 210 | if (!debugDir.exists()) 211 | debugDir.mkdir(); 212 | File f = new File("debug/" + className.replace("/", ".") + ".class"); 213 | FileOutputStream fos = new FileOutputStream(f); 214 | fos.write(cw.toByteArray()); 215 | fos.close(); 216 | } 217 | return cw.toByteArray(); 218 | } catch (Throwable t) { 219 | t.printStackTrace(); 220 | } 221 | } 222 | if (classBeingRedefined == null && isClassThatNeedsReflectionHacked(className)) { 223 | try { 224 | ClassReader cr = new ClassReader(classfileBuffer); 225 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 226 | ReflectionFixingCV cv = new ReflectionFixingCV(cw); 227 | cr.accept(cv, 0); 228 | if (DEBUG) { 229 | File debugDir = new File("debug"); 230 | if (!debugDir.exists()) 231 | debugDir.mkdir(); 232 | File f = new File("debug/" + className.replace("/", ".") + ".class"); 233 | FileOutputStream fos = new FileOutputStream(f); 234 | fos.write(cw.toByteArray()); 235 | fos.close(); 236 | } 237 | return cw.toByteArray(); 238 | } catch (Throwable t) { 239 | t.printStackTrace(); 240 | } 241 | } 242 | if (isIgnoredClass(className)) { 243 | // System.out.println("Skip " + className); 244 | return null; 245 | } 246 | if (classBeingRedefined != null) { 247 | // System.err.println("Redefine!"); 248 | // return null; 249 | } 250 | // System.out.println("Inst " + className); 251 | try { 252 | // if(DEBUG) 253 | // System.err.println("VMVMClassfiletransformer PLAIN " + className + " in " + loader); 254 | // new Exception().printStackTrace(); 255 | ClassReader cr = new ClassReader(classfileBuffer); 256 | 257 | if(DEBUG) 258 | { 259 | if (DEBUG) { 260 | File debugDir = new File("debug-uninst"); 261 | if (!debugDir.exists()) 262 | debugDir.mkdir(); 263 | File f = new File("debug-uninst/" + className.replace("/", ".") + ".class"); 264 | try{ 265 | FileOutputStream fos = new FileOutputStream(f); 266 | fos.write(classfileBuffer); 267 | fos.close(); 268 | } 269 | catch(Throwable t) 270 | { 271 | t.printStackTrace(); 272 | } 273 | } 274 | } 275 | if (DEBUG) { 276 | ClassNode cn = new ClassNode(); 277 | cr.accept(cn, 0); 278 | for (Object s : cn.interfaces) { 279 | if (s.equals(Type.getInternalName(VMVMInstrumented.class))) 280 | return null; 281 | // throw new IllegalArgumentException(); 282 | } 283 | } 284 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 285 | ClassVisitor _cv = cw; 286 | if(DEBUG) 287 | _cv = new CheckClassAdapter(_cv, false); 288 | ClassReinitCV cv = new ClassReinitCV(_cv); 289 | cr.accept(cv, ClassReader.EXPAND_FRAMES); 290 | byte[] ret = cw.toByteArray(); 291 | 292 | if (DEBUG) { 293 | File debugDir = new File("debug-plain"); 294 | if (!debugDir.exists()) 295 | debugDir.mkdir(); 296 | File f = new File("debug-plain/" + className.replace("/", ".") + ".class"); 297 | FileOutputStream fos = new FileOutputStream(f); 298 | fos.write(ret); 299 | fos.close(); 300 | } 301 | if (DEBUG) { 302 | ClassReader cr2 = new ClassReader(ret); 303 | cr2.accept(new CheckClassAdapter(new ClassWriter(0)), 0); 304 | } 305 | 306 | if (DEBUG) { 307 | File debugDir = new File("debug"); 308 | if (!debugDir.exists()) 309 | debugDir.mkdir(); 310 | File f = new File("debug/" + className.replace("/", ".") + ".class"); 311 | FileOutputStream fos = new FileOutputStream(f); 312 | fos.write(ret); 313 | fos.close(); 314 | } 315 | return ret; 316 | } catch (Throwable t) { 317 | //Make sure that an exception in instrumentation gets printed, rather than squelched 318 | System.err.println("In transformation for " + className + ":"); 319 | t.printStackTrace(); 320 | return null; 321 | } 322 | 323 | } 324 | 325 | private boolean hasClass(ClassLoader loader, String string) { 326 | try{ 327 | if(loader == null) 328 | Class.forName(string.replace("/", ".")); 329 | else 330 | loader.loadClass(string.replace("/", ".")); 331 | return true; 332 | } 333 | catch(Exception ex) 334 | { 335 | // System.out.println("Couldn't find " + string.replace("/", ".") + " in " + loader); 336 | return false; 337 | } 338 | } 339 | 340 | } 341 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/ClassReinitCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import java.edu.columbia.cs.psl.vmvm.runtime.InterfaceReinitializer; 4 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 5 | import edu.columbia.cs.psl.vmvm.runtime.VMVMClassFileTransformer; 6 | import org.objectweb.asm.*; 7 | import org.objectweb.asm.commons.AnalyzerAdapter; 8 | import org.objectweb.asm.commons.JSRInlinerAdapter; 9 | import org.objectweb.asm.tree.FieldNode; 10 | import org.objectweb.asm.tree.MethodNode; 11 | import org.objectweb.asm.tree.TryCatchBlockNode; 12 | import org.objectweb.asm.util.CheckClassAdapter; 13 | 14 | import java.util.HashSet; 15 | import java.util.LinkedList; 16 | import java.util.concurrent.ConcurrentHashMap; 17 | 18 | public class ClassReinitCV extends ClassVisitor { 19 | 20 | 21 | public ClassReinitCV(ClassVisitor parent) { 22 | super(Opcodes.ASM5, new CheckClassAdapter(parent,false)); 23 | 24 | } 25 | 26 | private boolean isInterface; 27 | private String className; 28 | private boolean skipFrames; 29 | private LinkedList allStaticFields = new LinkedList(); 30 | private HashSet finalFields = new HashSet(); 31 | private boolean fixLdcClass; 32 | private boolean isEnum; 33 | 34 | public static ConcurrentHashMap reClinitMethods = new ConcurrentHashMap<>(); 35 | public static ConcurrentHashMap reClinitClassHelperVersions = new ConcurrentHashMap<>(); 36 | 37 | public HashSet getFinalFields() { 38 | return finalFields; 39 | } 40 | public LinkedList getAllStaticFields() { 41 | return allStaticFields; 42 | } 43 | public MethodNode getReClinitMethod() { 44 | return reClinitMethod; 45 | } 46 | 47 | public int version; 48 | 49 | private HashSet ownersOfStaticFields = new HashSet(); 50 | 51 | public HashSet getOwnersOfStaticFields() { 52 | return ownersOfStaticFields; 53 | } 54 | 55 | private HashSet ignoredFields = new HashSet<>(); 56 | private boolean isIgnoredField(int acc, String name){ 57 | if(name.equals("serialVersionUID")) 58 | return true; 59 | if(name.equals("$VALUES") && isEnum) { 60 | ignoredFields.add(name); 61 | return true; 62 | } 63 | if((acc & Opcodes.ACC_ENUM) != 0) { 64 | ignoredFields.add(name); 65 | return true; 66 | } 67 | return false; 68 | } 69 | @Override 70 | public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 71 | if(!isInterface && !isIgnoredField(access, name)) 72 | access = access & ~Opcodes.ACC_FINAL; 73 | if((access & Opcodes.ACC_STATIC) != 0 && !isIgnoredField(access, name)) { 74 | access = access & ~Opcodes.ACC_PRIVATE; 75 | access = access & ~Opcodes.ACC_PROTECTED; 76 | access = access | Opcodes.ACC_PUBLIC; 77 | allStaticFields.add(new FieldNode(access, name, desc, signature, value)); 78 | } 79 | return super.visitField(access, name, desc, signature, value); 80 | } 81 | 82 | String[] interfaces; 83 | String superName; 84 | 85 | @Override 86 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 87 | this.isInterface = (access & Opcodes.ACC_INTERFACE) != 0; 88 | this.isEnum = (access & Opcodes.ACC_ENUM) != 0; 89 | this.className = name; 90 | this.fixLdcClass = (version & 0xFFFF) < Opcodes.V1_5; 91 | this.version = version; 92 | this.interfaces = interfaces; 93 | this.superName = superName; 94 | skipFrames = false; 95 | if (version >= 100 || version <= 50) 96 | skipFrames = true; 97 | if ((access & Opcodes.ACC_PUBLIC) == 0) { 98 | access = access & ~Opcodes.ACC_PROTECTED; 99 | access = access & ~Opcodes.ACC_PRIVATE; 100 | access = access | Opcodes.ACC_PUBLIC; 101 | } 102 | reClinitClassHelperVersions.put(this.className, this.version); 103 | //Add signal interface 104 | String[] newInterfaces = new String[interfaces.length + 1]; 105 | System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length); 106 | newInterfaces[interfaces.length] = "java/edu/columbia/cs/psl/vmvm/runtime/VMVMInstrumented"; 107 | super.visit(version, access, name, signature, superName, newInterfaces); 108 | } 109 | 110 | MethodNode clinitMethod; 111 | 112 | @Override 113 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 114 | MethodVisitor mv; 115 | if (name.equals("")) { 116 | clinitMethod = new MethodNode(access, name, desc, signature, exceptions); 117 | mv = clinitMethod; 118 | } else 119 | mv = super.visitMethod(access, name, desc, signature, exceptions); 120 | mv = new SystemPropertyLogger(mv); 121 | mv = new ReflectionFixingMV(mv, fixLdcClass, className); 122 | AnalyzerAdapter an = new AnalyzerAdapter(className, access, name, desc, mv); 123 | mv = new ReinitCheckForceMV(an, an, className, name, (access & Opcodes.ACC_STATIC) != 0, fixLdcClass, skipFrames); 124 | mv = new JSRInlinerAdapter(mv, access, name, desc, signature, exceptions); 125 | 126 | return mv; 127 | } 128 | 129 | private MethodNode reClinitMethod; 130 | 131 | @Override 132 | public void visitEnd() { 133 | String classNameWField = className; 134 | if (isInterface) 135 | classNameWField = className + "$$VMVM_RESETTER"; 136 | 137 | if (!isInterface) { 138 | super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;", null, null); 139 | super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT, Constants.VMVM_NEEDS_RESET, "Z", null, 0); 140 | super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT, Constants.VMVM_RESET_FIELD, "L"+ InterfaceReinitializer.INTERNAL_NAME +";", null, null); 141 | } 142 | else 143 | { 144 | super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, Constants.VMVM_RESET_FIELD, "L"+ InterfaceReinitializer.INTERNAL_NAME +";", null, null); 145 | super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, Constants.VMVM_NEEDS_RESET, "Z", null, 0); 146 | } 147 | 148 | //Create a new 149 | MethodVisitor mv = super.visitMethod(Opcodes.ACC_STATIC, "", "()V", null, null); 150 | mv.visitCode(); 151 | 152 | if (fixLdcClass) { 153 | mv.visitLdcInsn(className.replace("/", ".")); 154 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 155 | } else 156 | mv.visitLdcInsn(Type.getObjectType(className)); 157 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "clinitCalled", "(Ljava/lang/Class;)L" + InterfaceReinitializer.INTERNAL_NAME + ";", false); 158 | mv.visitFieldInsn(Opcodes.PUTSTATIC, className, Constants.VMVM_RESET_FIELD, "L" + InterfaceReinitializer.INTERNAL_NAME + ";"); 159 | 160 | if (!VMVMClassFileTransformer.isIgnoredClass(superName)) 161 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, superName, "__vmvmReClinit", "()V", false); 162 | for(String i : interfaces) 163 | { 164 | if(!VMVMClassFileTransformer.isIgnoredClass(i)) 165 | { 166 | mv.visitFieldInsn(Opcodes.GETSTATIC, i, Constants.VMVM_RESET_FIELD,"L"+InterfaceReinitializer.INTERNAL_NAME+";"); 167 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, InterfaceReinitializer.INTERNAL_NAME, "__vmvmReClinit", "()V", false); 168 | 169 | } 170 | } 171 | 172 | if (clinitMethod != null) { 173 | if (clinitMethod.maxStack < 6) 174 | clinitMethod.maxStack = 6; 175 | clinitMethod.accept(mv); 176 | } else { 177 | mv.visitInsn(Opcodes.RETURN); 178 | mv.visitMaxs(6, 0); 179 | mv.visitEnd(); 180 | } 181 | 182 | if (isInterface) { 183 | reClinitMethod = new MethodNode(Opcodes.ACC_PUBLIC, "__vmvmReClinit", "()V", null, null); 184 | 185 | mv = new PutStaticHelperMV(reClinitMethod, className, fixLdcClass); 186 | } else 187 | mv = super.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, "__vmvmReClinit", "()V", null, null); 188 | 189 | if(isEnum){ 190 | mv = new MethodVisitor(Opcodes.ASM5, mv) { 191 | @Override 192 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 193 | if(opcode == Opcodes.PUTSTATIC && owner.equals(className) && ignoredFields.contains(name)) 194 | super.visitInsn(Opcodes.POP); 195 | else 196 | super.visitFieldInsn(opcode, owner, name, desc); 197 | } 198 | }; 199 | } 200 | if(reClinitMethod != null) 201 | { 202 | reClinitMethods.put(className, reClinitMethod); 203 | } 204 | final Label finishedClinitCode = new Label(); 205 | LabelRemappingMV reLabeler = new LabelRemappingMV(mv, finishedClinitCode); 206 | mv.visitCode(); 207 | 208 | if (clinitMethod != null) { 209 | if (clinitMethod.tryCatchBlocks != null) { 210 | for (Object o : clinitMethod.tryCatchBlocks) { 211 | ((TryCatchBlockNode) o).accept(reLabeler); 212 | } 213 | } 214 | } 215 | Label allDone = new Label(); 216 | 217 | Label continu = new Label(); 218 | 219 | mv.visitFieldInsn(Opcodes.GETSTATIC, className, Constants.VMVM_NEEDS_RESET, "Z"); 220 | mv.visitJumpInsn(Opcodes.IFEQ, allDone); 221 | if (fixLdcClass) { 222 | mv.visitLdcInsn(className.replace("/", ".")); 223 | mv.visitInsn(Opcodes.ICONST_0); 224 | mv.visitLdcInsn(className.replace("/", ".")); 225 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 226 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;", false); 227 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); 228 | } else 229 | mv.visitLdcInsn(Type.getObjectType(className)); 230 | 231 | mv.visitInsn(Opcodes.DUP); 232 | mv.visitInsn(Opcodes.MONITORENTER); 233 | 234 | mv.visitFieldInsn(Opcodes.GETSTATIC, classNameWField, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); 235 | Label notInInit = new Label(); 236 | mv.visitJumpInsn(Opcodes.IFNULL, notInInit); 237 | 238 | mv.visitFieldInsn(Opcodes.GETSTATIC, classNameWField, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); 239 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); 240 | mv.visitJumpInsn(Opcodes.IF_ACMPEQ, continu); 241 | //If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this procedure. 242 | //If the Class object for C indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally 243 | 244 | mv.visitInsn(Opcodes.DUP); 245 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "wait", "()V", false); 246 | //XXX what? 247 | mv.visitLabel(notInInit); 248 | if (!skipFrames) 249 | mv.visitFrame(Opcodes.F_NEW, 0, new Object[0], 1, new Object[] { "java/lang/Class" }); 250 | mv.visitFieldInsn(Opcodes.GETSTATIC, className, Constants.VMVM_NEEDS_RESET, "Z"); 251 | mv.visitJumpInsn(Opcodes.IFEQ, continu); 252 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); 253 | mv.visitFieldInsn(Opcodes.PUTSTATIC, classNameWField, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); 254 | mv.visitInsn(Opcodes.ICONST_0); 255 | mv.visitFieldInsn(Opcodes.PUTSTATIC, className, Constants.VMVM_NEEDS_RESET, "Z"); 256 | 257 | 258 | mv.visitInsn(Opcodes.DUP); 259 | mv.visitInsn(Opcodes.MONITOREXIT); 260 | // mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, Constants.VMVM_STATIC_RESET_METHOD, "()V", false); 261 | //do the init 262 | 263 | // if (fixLdcClass) { 264 | // mv.visitLdcInsn(className.replace("/", ".")); 265 | // mv.visitInsn(Opcodes.ICONST_0); 266 | // mv.visitLdcInsn(className.replace("/", ".")); 267 | // mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 268 | // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;", false); 269 | // mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); 270 | // } else 271 | // mv.visitLdcInsn(Type.getObjectType(className)); 272 | 273 | for (FieldNode fn : allStaticFields) { 274 | if(isInterface & fn.value != null) 275 | continue; //constants dont' need to get reset 276 | if (fn.value != null) { 277 | mv.visitLdcInsn(fn.value); 278 | mv.visitFieldInsn(Opcodes.PUTSTATIC, className, fn.name, fn.desc); 279 | } else { 280 | switch (Type.getType(fn.desc).getSort()) { 281 | case Type.OBJECT: 282 | case Type.ARRAY: 283 | mv.visitInsn(Opcodes.ACONST_NULL); 284 | break; 285 | case Type.DOUBLE: 286 | mv.visitInsn(Opcodes.DCONST_0); 287 | break; 288 | case Type.LONG: 289 | mv.visitInsn(Opcodes.ICONST_0); 290 | mv.visitInsn(Opcodes.I2L); 291 | break; 292 | case Type.FLOAT: 293 | mv.visitInsn(Opcodes.FCONST_0); 294 | break; 295 | default: 296 | mv.visitInsn(Opcodes.ICONST_0); 297 | break; 298 | } 299 | mv.visitFieldInsn(Opcodes.PUTSTATIC, className, fn.name, fn.desc); 300 | } 301 | } 302 | 303 | if (!VMVMClassFileTransformer.isIgnoredClass(superName)) 304 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, superName, "__vmvmReClinit", "()V", false); 305 | 306 | for(String i : interfaces) 307 | { 308 | if(!VMVMClassFileTransformer.isIgnoredClass(i)) 309 | { 310 | mv.visitFieldInsn(Opcodes.GETSTATIC, i, Constants.VMVM_RESET_FIELD,"L"+InterfaceReinitializer.INTERNAL_NAME+";"); 311 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, InterfaceReinitializer.INTERNAL_NAME, "__vmvmReClinit", "()V", false); 312 | 313 | } 314 | } 315 | if (fixLdcClass) { 316 | mv.visitLdcInsn(className.replace("/", ".")); 317 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 318 | } else 319 | mv.visitLdcInsn(Type.getObjectType(className)); 320 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "reinitCalled", "(Ljava/lang/Class;)V", false); 321 | if (isEnum) { 322 | if (fixLdcClass) { 323 | mv.visitLdcInsn(className.replace("/", ".")); 324 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 325 | } else 326 | mv.visitLdcInsn(Type.getObjectType(className)); 327 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "fixEnum", "(Ljava/lang/Class;)V", false); 328 | 329 | } 330 | int maxStack = 40; 331 | int maxLocals = 40; 332 | if (clinitMethod != null) { 333 | mv.visitInsn(Opcodes.POP); 334 | maxStack = (clinitMethod.maxStack > 3 ? clinitMethod.maxStack : 0); 335 | maxLocals = (clinitMethod.maxLocals > 2 ? clinitMethod.maxLocals : 0); 336 | clinitMethod.instructions.accept(reLabeler); 337 | mv.visitLabel(finishedClinitCode); 338 | if (!skipFrames) 339 | mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 0, new Object[0]); 340 | if (fixLdcClass) { 341 | mv.visitLdcInsn(classNameWField.replace("/", ".")); 342 | mv.visitInsn(Opcodes.ICONST_0); 343 | mv.visitLdcInsn(classNameWField.replace("/", ".")); 344 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 345 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;", false); 346 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); 347 | } else 348 | mv.visitLdcInsn(Type.getObjectType(classNameWField)); 349 | } 350 | //If the execution of the class or interface initialization method completes normally, then acquire LC, label the Class object for C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally. 351 | mv.visitInsn(Opcodes.DUP); 352 | mv.visitInsn(Opcodes.MONITORENTER); 353 | mv.visitInsn(Opcodes.ACONST_NULL); 354 | mv.visitFieldInsn(Opcodes.PUTSTATIC, classNameWField, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); 355 | mv.visitInsn(Opcodes.DUP); 356 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "notifyAll", "()V", false); 357 | // 358 | mv.visitLabel(continu); 359 | if (!skipFrames) 360 | mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 1, new Object[] { "java/lang/Class" }); 361 | mv.visitInsn(Opcodes.MONITOREXIT); 362 | mv.visitLabel(allDone); 363 | if (!skipFrames) 364 | mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 0, new Object[0]); 365 | 366 | mv.visitInsn(Opcodes.RETURN); 367 | mv.visitMaxs(maxStack, maxLocals); 368 | mv.visitEnd(); 369 | 370 | super.visitEnd(); 371 | } 372 | 373 | public void println(MethodVisitor mv, String toPrint) { 374 | mv.visitLdcInsn(toPrint); 375 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "logMessage", "(Ljava/lang/String;)V", false); 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/Constants.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | public interface Constants { 4 | public static final String VMVM_RESET_IN_PROGRESS = "VMVM_RESET_IN_PROGRESS"; 5 | public static final String VMVM_NEEDS_RESET = "VMVM_NEEDS_RESET"; 6 | public static final String VMVM_RESET_FIELD = "$$VMVM_RESETTER"; 7 | } 8 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/LabelRemappingMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import org.objectweb.asm.Label; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | import java.util.HashMap; 8 | 9 | public class LabelRemappingMV extends MethodVisitor { 10 | private HashMap newLabels = new HashMap(); 11 | private Label finishedClinitCode; 12 | 13 | public LabelRemappingMV(MethodVisitor mv, Label finishedClinitlbl) { 14 | super(Opcodes.ASM5, mv); 15 | this.finishedClinitCode = finishedClinitlbl; 16 | } 17 | 18 | private Label remapLabel(Label l) { 19 | if (newLabels.containsKey(l)) 20 | return newLabels.get(l); 21 | Label r = new Label(); 22 | newLabels.put(l, r); 23 | return r; 24 | } 25 | 26 | @Override 27 | public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { 28 | if (stack != null) { 29 | Object[] newStack = new Object[stack.length]; 30 | for (int i = 0; i < stack.length; i++) 31 | if (stack[i] instanceof Label) 32 | newStack[i] = remapLabel((Label) stack[i]); 33 | else 34 | newStack[i] = stack[i]; 35 | super.visitFrame(type, nLocal, local, nStack, newStack); 36 | } else 37 | super.visitFrame(type, nLocal, local, nStack, stack); 38 | } 39 | 40 | @Override 41 | public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { 42 | Label[] newLabels = new Label[labels.length]; 43 | for (int i = 0; i < labels.length; i++) 44 | newLabels[i] = remapLabel(labels[i]); 45 | dflt = remapLabel(dflt); 46 | super.visitTableSwitchInsn(min, max, dflt, newLabels); 47 | } 48 | 49 | @Override 50 | public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 51 | super.visitTryCatchBlock(remapLabel(start), remapLabel(end), remapLabel(handler), type); 52 | } 53 | 54 | @Override 55 | public void visitLineNumber(int line, Label start) { 56 | super.visitLineNumber(line, remapLabel(start)); 57 | } 58 | 59 | @Override 60 | public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { 61 | super.visitLocalVariable(name, desc, signature, remapLabel(start), remapLabel(end), index); 62 | } 63 | 64 | @Override 65 | public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 66 | Label[] newLabels = new Label[labels.length]; 67 | for (int i = 0; i < labels.length; i++) 68 | newLabels[i] = remapLabel(labels[i]); 69 | dflt = remapLabel(dflt); 70 | super.visitLookupSwitchInsn(dflt, keys, newLabels); 71 | } 72 | 73 | @Override 74 | public void visitJumpInsn(int opcode, Label label) { 75 | super.visitJumpInsn(opcode, remapLabel(label)); 76 | } 77 | 78 | @Override 79 | public void visitLabel(Label label) { 80 | super.visitLabel(remapLabel(label)); 81 | } 82 | 83 | @Override 84 | public void visitInsn(int opcode) { 85 | if (opcode == Opcodes.RETURN) { 86 | super.visitJumpInsn(Opcodes.GOTO, finishedClinitCode); 87 | } else 88 | super.visitInsn(opcode); 89 | } 90 | 91 | @Override 92 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 93 | super.visitMethodInsn(opcode, owner, name, desc, itf); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/PlaceholderClasswriter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import org.objectweb.asm.ClassWriter; 4 | 5 | import java.util.LinkedList; 6 | 7 | public class PlaceholderClasswriter extends ClassWriter { 8 | 9 | private int place; 10 | private int place2; 11 | private LinkedList interfacePlaces = new LinkedList(); 12 | 13 | public PlaceholderClasswriter(int flags) { 14 | super(flags); 15 | } 16 | 17 | public int getPlace() { 18 | return place; 19 | } 20 | 21 | public int getPlace2() { 22 | return place2; 23 | } 24 | 25 | public LinkedList getInterfacePlaces() { 26 | return interfacePlaces; 27 | } 28 | 29 | @Override 30 | public int newClass(String value) { 31 | return super.newClass(value); 32 | } 33 | 34 | @Override 35 | public int newUTF8(String value) { 36 | int ret = super.newUTF8(value); 37 | if ("net/jonbell/PlaceHolder".equals(value)) { 38 | place = ret; 39 | } else if ("net/jonbell/PlaceHolder2".equals(value)) { 40 | place2 = ret; 41 | } else if (value != null && value.startsWith("net/jonbell/IFacePlaceHolder")) { 42 | interfacePlaces.add(ret); 43 | } 44 | return ret; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/PutStaticHelperMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import java.edu.columbia.cs.psl.vmvm.runtime.ReflectionWrapper; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.Type; 7 | 8 | public class PutStaticHelperMV extends MethodVisitor { 9 | private String className; 10 | private boolean fixLdcClass; 11 | public PutStaticHelperMV(MethodVisitor mv, String className, boolean fixLdcClass) { 12 | super(Opcodes.ASM5, mv); 13 | this.className = className; 14 | this.fixLdcClass = fixLdcClass; 15 | } 16 | 17 | @Override 18 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 19 | if(opcode == Opcodes.PUTSTATIC && owner.equals(className)) 20 | { 21 | if (fixLdcClass) { 22 | super.visitLdcInsn(owner.replace("/", ".")); 23 | super.visitMethodInsn(org.objectweb.asm.Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 24 | } else 25 | super.visitLdcInsn(Type.getObjectType(owner)); 26 | super.visitLdcInsn(name); 27 | Type t = Type.getType(desc); 28 | switch(t.getSort()){ 29 | case Type.ARRAY: 30 | case Type.OBJECT: 31 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), "putStaticField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/String;)V",false); 32 | break; 33 | default: 34 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), "putStaticField", "("+t.getDescriptor()+"Ljava/lang/Class;Ljava/lang/String;)V",false); 35 | break; 36 | } 37 | 38 | } 39 | else { 40 | super.visitFieldInsn(opcode, owner, name, desc); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/ReflectionFixingCV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class ReflectionFixingCV extends ClassVisitor { 8 | public ReflectionFixingCV(ClassVisitor cv) { 9 | super(Opcodes.ASM5, cv); 10 | } 11 | 12 | private boolean fixLdcClass = false; 13 | private String className; 14 | 15 | @Override 16 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 17 | super.visit(version, access, name, signature, superName, interfaces); 18 | this.fixLdcClass = (version & 0xFFFF) < Opcodes.V1_5; 19 | this.className = name; 20 | } 21 | 22 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 23 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 24 | return new ReflectionFixingMV(mv, fixLdcClass, className); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/ReflectionFixingMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | 6 | import org.objectweb.asm.MethodVisitor; 7 | import org.objectweb.asm.Opcodes; 8 | import org.objectweb.asm.Type; 9 | import org.objectweb.asm.commons.InstructionAdapter; 10 | 11 | import java.edu.columbia.cs.psl.vmvm.runtime.ReflectionWrapper; 12 | 13 | public class ReflectionFixingMV extends InstructionAdapter implements Opcodes { 14 | 15 | private boolean oldClassldcHack; 16 | private String className; 17 | 18 | public ReflectionFixingMV(MethodVisitor mv, boolean oldClassldcHack, String className) { 19 | super(Opcodes.ASM5, mv); 20 | this.className = className; 21 | this.oldClassldcHack = oldClassldcHack; 22 | } 23 | 24 | @Override 25 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itfc) { 26 | if (Type.getInternalName(Class.class).equals(owner) && name.equals("newInstance")) { 27 | // owner = Type.getInternalName(ReflectionWrapper.class); 28 | // opcode = INVOKESTATIC; 29 | super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), "preNewInstance", "(Ljava/lang/Class;)Ljava/lang/Class;", false); 30 | super.visitMethodInsn(opcode, owner, name, desc, itfc); 31 | } else if (owner.equals("java/lang/reflect/Field") && name.equals("getType")) { 32 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), name, "(Ljava/lang/reflect/Field;)Ljava/lang/Class;", false); 33 | 34 | } else if ((Type.getInternalName(Class.class).equals(owner) && name.equals("forName"))) { 35 | owner = Type.getInternalName(ReflectionWrapper.class); 36 | if (desc.contains("ClassLoader")) 37 | super.visitMethodInsn(opcode, owner, name, desc, itfc); 38 | else { 39 | if (!oldClassldcHack)// java 5+ 40 | super.visitLdcInsn(Type.getType("L" + className + ";")); 41 | else { 42 | super.visitLdcInsn(className.replace("/", ".")); 43 | super.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); 44 | } 45 | super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;", false); 46 | super.visitMethodInsn(opcode, owner, name, desc.substring(0, desc.indexOf(")")) + Type.getDescriptor(ClassLoader.class) + desc.substring(desc.indexOf(")")), itfc); 47 | } 48 | } else if ((Type.getInternalName(Class.class).equals(owner) && (name.equals("getDeclaredFields")||name.equals("getInterfaces") || name.equals("getDeclaredMethods") || name.equals("getFields") || name.equals("getMethods")))) { 49 | desc = "(" + Type.getDescriptor(Class.class) + ")" + Type.getReturnType(desc).getDescriptor(); 50 | super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), name, desc, false); 51 | } else if ((Type.getInternalName(Method.class).equals(owner) && name.equals("invoke"))) { 52 | owner = Type.getInternalName(ReflectionWrapper.class); 53 | opcode = INVOKESTATIC; 54 | 55 | super.visitMethodInsn(opcode, owner, name, "(Ljava/lang/reflect/Method;" + desc.substring(1), false); 56 | } else if ((Type.getInternalName(Method.class).equals(owner) && name.equals("getModifiers"))) { 57 | owner = Type.getInternalName(ReflectionWrapper.class); 58 | opcode = INVOKESTATIC; 59 | 60 | super.visitMethodInsn(opcode, owner, name, "(Ljava/lang/reflect/Method;" + desc.substring(1), false); 61 | } else if ((Type.getInternalName(Class.class).equals(owner) && name.equals("getModifiers"))) { 62 | owner = Type.getInternalName(ReflectionWrapper.class); 63 | opcode = INVOKESTATIC; 64 | 65 | super.visitMethodInsn(opcode, owner, name, "(Ljava/lang/Class;" + desc.substring(1), false); 66 | } else if ((Type.getInternalName(Field.class).equals(owner) && name.equals("getModifiers"))) { 67 | owner = Type.getInternalName(ReflectionWrapper.class); 68 | opcode = INVOKESTATIC; 69 | 70 | super.visitMethodInsn(opcode, owner, name, "(Ljava/lang/reflect/Field;" + desc.substring(1), false); 71 | } else if ((Type.getInternalName(Field.class).equals(owner) && (name.equals("getBoolean") || name.equals("getByte") || name.equals("getChar") || name.equals("getDouble") 72 | || name.equals("getFloat") || name.equals("getInt") || name.equals("getLong") || name.equals("get")))) { 73 | if (name.equals("get")) 74 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), "get", "(Ljava/lang/reflect/Field;Ljava/lang/Object;)Ljava/lang/Object;", false); 75 | else 76 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), name, "(Ljava/lang/reflect/Field;" + desc.substring(1), false); 77 | } else if (Type.getInternalName(Field.class).equals(owner) 78 | && (name.equals("setBoolean") || name.equals("setByte") || name.equals("setChar") || name.equals("setDouble") || name.equals("setFloat") || name.equals("setInt") 79 | || name.equals("setLong") || name.equals("set"))) { 80 | 81 | if (name.equals("set")) 82 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), "set", "(Ljava/lang/reflect/Field;Ljava/lang/Object;Ljava/lang/Object;)V", false); 83 | else { 84 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReflectionWrapper.class), name, "(Ljava/lang/reflect/Field;" + desc.substring(1), false); 85 | } 86 | 87 | } else { 88 | super.visitMethodInsn(opcode, owner, name, desc, itfc); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/ReinitCheckForceMV.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import java.edu.columbia.cs.psl.vmvm.runtime.InterfaceReinitializer; 4 | import java.edu.columbia.cs.psl.vmvm.runtime.MutableInstance; 5 | import edu.columbia.cs.psl.vmvm.runtime.VMVMClassFileTransformer; 6 | import org.objectweb.asm.Label; 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | import org.objectweb.asm.commons.AnalyzerAdapter; 10 | import org.objectweb.asm.tree.FrameNode; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | 16 | public class ReinitCheckForceMV extends MethodVisitor { 17 | private AnalyzerAdapter an; 18 | private boolean isStaticMethod; 19 | private String owner; 20 | private boolean needOldLdc; 21 | private String name; 22 | private boolean skipFrames; 23 | private boolean doOpt = false; 24 | public ReinitCheckForceMV(MethodVisitor mv, AnalyzerAdapter analyzer, String owner, String name, boolean isStaticMethod, boolean needOldLdc, boolean skipFrames) { 25 | super(Opcodes.ASM5, mv); 26 | this.isStaticMethod = isStaticMethod; 27 | this.owner = owner; 28 | this.name = name; 29 | this.an = analyzer; 30 | this.needOldLdc = needOldLdc; 31 | this.skipFrames = skipFrames; 32 | } 33 | 34 | public static Object[] removeLongsDoubleTopVal(List in) { 35 | ArrayList ret = new ArrayList(); 36 | boolean lastWas2Word = false; 37 | for (Object n : in) { 38 | if (n == Opcodes.TOP && lastWas2Word) { 39 | //nop 40 | } else 41 | ret.add(n); 42 | if (n == Opcodes.DOUBLE || n == Opcodes.LONG) 43 | lastWas2Word = true; 44 | else 45 | lastWas2Word = false; 46 | } 47 | return ret.toArray(); 48 | } 49 | 50 | public FrameNode getCurrentFrame() { 51 | if (skipFrames) 52 | return null; 53 | if (an.locals == null || an.stack == null) 54 | throw new IllegalArgumentException("In " + owner + "." + name); 55 | Object[] locals = removeLongsDoubleTopVal(an.locals); 56 | Object[] stack = removeLongsDoubleTopVal(an.stack); 57 | FrameNode ret = new FrameNode(Opcodes.F_NEW, locals.length, locals, stack.length, stack); 58 | return ret; 59 | } 60 | 61 | public void println(String toPrint) { 62 | visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 63 | visitLdcInsn(toPrint + " : "); 64 | super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); 65 | 66 | visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 67 | super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); 68 | super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getName", "()Ljava/lang/String;", false); 69 | super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 70 | } 71 | 72 | @Override 73 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 74 | 75 | if ((opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC) && !VMVMClassFileTransformer.isIgnoredClass(owner) 76 | && !name.equals(Constants.VMVM_NEEDS_RESET) 77 | && !desc.equals("L" + MutableInstance.INTERNAL_NAME + ";") 78 | && !name.equals("$$VMVM_RESETTER") 79 | && !name.equals(Constants.VMVM_RESET_IN_PROGRESS)) { 80 | addCheck(owner); 81 | } 82 | super.visitFieldInsn(opcode, owner, name, desc); 83 | } 84 | 85 | 86 | private void addCheck(String owner){ 87 | if(!checked.add(owner) && !this.name.contains("test")) 88 | return; 89 | Label ok = new Label(); 90 | FrameNode fn = getCurrentFrame(); 91 | super.visitFieldInsn(Opcodes.GETSTATIC, owner, Constants.VMVM_NEEDS_RESET, "Z"); 92 | 93 | super.visitJumpInsn(Opcodes.IFEQ, ok); 94 | super.visitFieldInsn(Opcodes.GETSTATIC, owner, Constants.VMVM_RESET_FIELD, "L"+InterfaceReinitializer.INTERNAL_NAME+";"); 95 | super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, InterfaceReinitializer.INTERNAL_NAME, "__vmvmReClinit", "()V", false); 96 | super.visitLabel(ok); 97 | if (!skipFrames) { 98 | fn.accept(this); 99 | super.visitInsn(Opcodes.NOP); 100 | } 101 | } 102 | HashSet checked = new HashSet<>(); 103 | @Override 104 | public void visitCode() { 105 | super.visitCode(); 106 | 107 | if ((name.equals("") || (isStaticMethod && !(name.equals("") || name.equals("__vmvmReClinit") || name.equals("_vmvmReinitFieldCheck")))) && !doOpt) { 108 | addCheck(owner); 109 | } 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/SystemPropertyLogger.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.HashMap; 5 | import java.util.Scanner; 6 | 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | import org.objectweb.asm.Type; 10 | import org.objectweb.asm.commons.InstructionAdapter; 11 | 12 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 13 | 14 | public class SystemPropertyLogger extends InstructionAdapter { 15 | 16 | 17 | public SystemPropertyLogger(final MethodVisitor mv) { 18 | super(Opcodes.ASM5,mv); 19 | } 20 | public static void main(String[] args) 21 | { 22 | for(String clazz : internalStatics.keySet()) 23 | { 24 | InternalStaticClass c = internalStatics.get(clazz); 25 | for(String s : c.setMethods.keySet()) 26 | { 27 | String fullSetMethod = clazz.replace("/", ".")+"."+s; 28 | String castType = ""; 29 | try { 30 | Class cl = Class.forName(clazz.replace("/", ".")); 31 | for(Method m : cl.getMethods()) 32 | { 33 | if(m.getName().equals(s) && m.getParameterTypes().length == 1) 34 | { 35 | castType = m.getParameterTypes()[0].getCanonicalName(); 36 | } 37 | } 38 | } catch (ClassNotFoundException e) { 39 | // TODO Auto-generated catch block 40 | e.printStackTrace(); 41 | } 42 | System.out.println("if(logsUsed["+c.setMethods.get(s)+"]){try{"); 43 | System.out.println(fullSetMethod+"(("+castType+")loggedValues["+c.setMethods.get(s)+"]);}catch(Exception ex){ex.printStackTrace();}logsUsed["+c.setMethods.get(s)+"]=false;loggedValues["+c.setMethods.get(s)+"]=null;"); 44 | System.out.println("}"); 45 | } 46 | 47 | // for(String s : c.addMethods.keySet()) 48 | // { 49 | // String fullSetMethod = clazz.replace("/", ".")+"."+s.replace("add", "remove"); 50 | // String castType = ""; 51 | // try { 52 | // Class cl = Class.forName(clazz.replace("/", ".")); 53 | // for(Method m : cl.getMethods()) 54 | // { 55 | // if(m.getName().equals(s) && m.getParameterTypes().length == 1) 56 | // { 57 | // castType = m.getParameterTypes()[0].getCanonicalName(); 58 | // } 59 | // } 60 | // } catch (ClassNotFoundException e) { 61 | // // TODO Auto-generated catch block 62 | // e.printStackTrace(); 63 | // } 64 | // System.out.println("if(logsUsed["+c.addMethods.get(s)+"]){"); 65 | // System.out.println("for(WeakReference o : (LinkedList>) loggedValues["+c.addMethods.get(s)+"])"); 66 | // System.out.println("if(!o.isEnqueued()) "+fullSetMethod+"(("+castType+")o.get());"); 67 | // System.out.println("loggedValues["+c.addMethods.get(s)+"]=null;logsUsed["+c.addMethods.get(s)+"]=false;}"); 68 | // } 69 | // 70 | // 71 | // for(String s : c.removeMethods.keySet()) 72 | // { 73 | // String fullSetMethod = clazz.replace("/", ".")+"."+s.replace("remove", "add"); 74 | // String castType = ""; 75 | // try { 76 | // Class cl = Class.forName(clazz.replace("/", ".")); 77 | // for(Method m : cl.getMethods()) 78 | // { 79 | // if(m.getName().equals(s) && m.getParameterTypes().length == 1) 80 | // { 81 | // castType = m.getParameterTypes()[0].getCanonicalName(); 82 | // } 83 | // } 84 | // } catch (ClassNotFoundException e) { 85 | // // TODO Auto-generated catch block 86 | // e.printStackTrace(); 87 | // } 88 | // System.out.println("if(logsUsed["+c.removeMethods.get(s)+"]){"); 89 | // System.out.println("for(Object o : (LinkedList) loggedValues["+c.removeMethods.get(s)+"])"); 90 | // System.out.println(fullSetMethod+"(("+castType+")o);"); 91 | // System.out.println("loggedValues["+c.removeMethods.get(s)+"]=null;logsUsed["+c.removeMethods.get(s)+"]=false;}"); 92 | // } 93 | } 94 | } 95 | 96 | public static HashMap internalStatics = new HashMap<>(); 97 | static { 98 | int n = 0; 99 | Scanner s = new Scanner(Reinitializer.class.getResourceAsStream("internal-statics")); 100 | 101 | while (s.hasNextLine()) { 102 | String l = s.nextLine(); 103 | String[] d = l.split("\t"); 104 | String name = d[0]; 105 | InternalStaticClass c = new InternalStaticClass(); 106 | for (String z : d[1].split(",")) { 107 | if (z.length() > 0) 108 | c.addMethods.put(z, ++n); 109 | } 110 | for (String z : d[2].split(",")) 111 | if (z.length() > 0) 112 | c.removeMethods.put(z, ++n); 113 | for (String z : d[3].split(",")) 114 | if (z.length() > 0) 115 | c.setMethods.put(z, ++n); 116 | for (String z : d[4].split(",")) 117 | if (z.length() > 0) 118 | c.getMethods.put(z, -1); 119 | internalStatics.put(name, c); 120 | } 121 | s.close(); 122 | } 123 | @Override 124 | public void visitMethodInsn(int opcode, String owner, String name, 125 | String desc, boolean itfc) { 126 | if(owner.equals(Type.getInternalName(Runtime.class)) && name.equals("addShutdownHook")) 127 | { 128 | owner = Reinitializer.INTERNAL_NAME; 129 | desc = "("+Type.getDescriptor(Runtime.class)+Type.getDescriptor(Thread.class)+")V"; 130 | opcode = Opcodes.INVOKESTATIC; 131 | } 132 | if((owner.equals("java/lang/System") && name.equals("setProperty") && desc.equals("(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;")) 133 | || (owner.equals("java/lang/System") && name.equals("setProperties") && desc.equals("(Ljava/util/Properties;)V"))) 134 | { 135 | owner = Reinitializer.INTERNAL_NAME; 136 | name = "logAndSetProperty"; 137 | } 138 | if((owner.equals("java/lang/System") && name.equals("getProperty"))) 139 | { 140 | owner = Reinitializer.INTERNAL_NAME; 141 | name = "logAndGetProperty"; 142 | } 143 | else if(internalStatics.containsKey(owner)) 144 | { 145 | Type[] args =Type.getArgumentTypes(desc); 146 | InternalStaticClass clazz = internalStatics.get(owner); 147 | if(clazz.setMethods.keySet().contains(name) && args.length == 1) 148 | { 149 | //insert a fake get 150 | String newName = name.replace("set", "get"); 151 | if(owner.equals("javax/swing/JDialog") || owner.equals("javax/swing/JFrame")) 152 | newName = name.replace("set", "is"); 153 | if(owner.equals("java/lang/System") && (name.equals("setOut") || name.equals("setErr") || name.equals("setIn"))) 154 | { 155 | if( name.equals("setIn")) //.... 156 | super.visitFieldInsn(Opcodes.GETSTATIC, owner, "in", args[0].getDescriptor()); 157 | else 158 | super.visitFieldInsn(Opcodes.GETSTATIC, owner, name.replace("set", "").toLowerCase(), args[0].getDescriptor()); 159 | } 160 | else if(owner.equals("java/net/Authenticator") && name.equals("setDefault")) 161 | { 162 | super.visitInsn(Opcodes.ACONST_NULL); 163 | } 164 | else 165 | { 166 | super.visitMethodInsn(opcode, owner, newName, Type.getMethodDescriptor(args[0]), false); 167 | box(args[0]); 168 | } 169 | //Do the log 170 | //box if necessary 171 | super.visitIntInsn(Opcodes.BIPUSH, clazz.setMethods.get(name)); 172 | 173 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "logStaticInternal", "(Ljava/lang/Object;I)V", false); 174 | } 175 | else if(clazz.addMethods.containsKey(name)) 176 | { 177 | super.visitInsn(Opcodes.DUP); 178 | //Do the log 179 | //box if necessary 180 | box(args[0]); 181 | super.visitIntInsn(Opcodes.BIPUSH, clazz.addMethods.get(name)); 182 | 183 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "logStaticInternalAdd", "(Ljava/lang/Object;I)V", false); 184 | } 185 | else if(clazz.removeMethods.containsKey(name)) 186 | { 187 | super.visitInsn(Opcodes.DUP); 188 | //Do the log 189 | //box if necessary 190 | box(args[0]); 191 | super.visitIntInsn(Opcodes.BIPUSH, clazz.removeMethods.get(name)); 192 | super.visitMethodInsn(Opcodes.INVOKESTATIC, Reinitializer.INTERNAL_NAME, "logStaticInternalRemove", "(Ljava/lang/Object;I)V", false); 193 | } 194 | } 195 | super.visitMethodInsn(opcode, owner, name, desc, itfc); 196 | } 197 | public void box(final Type type) { 198 | if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 199 | return; 200 | } 201 | 202 | Type boxed = getBoxedType(type); 203 | super.visitTypeInsn(Opcodes.NEW , boxed.getInternalName()); 204 | 205 | if (type.getSize() == 2) { 206 | // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o 207 | dupX2(); 208 | dupX2(); 209 | pop(); 210 | } else { 211 | // p -> po -> opo -> oop -> o 212 | dupX1(); 213 | swap(); 214 | } 215 | super.visitMethodInsn(Opcodes.INVOKESPECIAL, boxed.getInternalName(), "", "("+type.getDescriptor()+")V", false); 216 | 217 | } 218 | private static Type getBoxedType(final Type type) { 219 | switch (type.getSort()) { 220 | case Type.BYTE: 221 | return BYTE_TYPE; 222 | case Type.BOOLEAN: 223 | return BOOLEAN_TYPE; 224 | case Type.SHORT: 225 | return SHORT_TYPE; 226 | case Type.CHAR: 227 | return CHARACTER_TYPE; 228 | case Type.INT: 229 | return INTEGER_TYPE; 230 | case Type.FLOAT: 231 | return FLOAT_TYPE; 232 | case Type.LONG: 233 | return LONG_TYPE; 234 | case Type.DOUBLE: 235 | return DOUBLE_TYPE; 236 | } 237 | return type; 238 | } 239 | private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte"); 240 | 241 | private static final Type BOOLEAN_TYPE = Type 242 | .getObjectType("java/lang/Boolean"); 243 | 244 | private static final Type SHORT_TYPE = Type 245 | .getObjectType("java/lang/Short"); 246 | 247 | private static final Type CHARACTER_TYPE = Type 248 | .getObjectType("java/lang/Character"); 249 | 250 | private static final Type INTEGER_TYPE = Type 251 | .getObjectType("java/lang/Integer"); 252 | 253 | private static final Type FLOAT_TYPE = Type 254 | .getObjectType("java/lang/Float"); 255 | 256 | private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long"); 257 | 258 | private static final Type DOUBLE_TYPE = Type 259 | .getObjectType("java/lang/Double"); 260 | 261 | public static class InternalStaticClass { 262 | public HashMap getMethods = new HashMap<>(); 263 | public HashMap setMethods = new HashMap<>(); 264 | public HashMap addMethods = new HashMap<>(); 265 | public HashMap removeMethods = new HashMap<>(); 266 | 267 | @Override 268 | public String toString() { 269 | return "InternalStaticClass [getMethods=" + getMethods + ", setMethods=" + setMethods + ", addMethods=" + addMethods + ", removeMethods=" + removeMethods + "]"; 270 | } 271 | 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /vmvm/src/main/java/edu/columbia/cs/psl/vmvm/runtime/inst/Utils.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.runtime.inst; 2 | 3 | import edu.columbia.cs.psl.vmvm.runtime.ConsumerUtils; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.Type; 7 | import org.objectweb.asm.commons.Method; 8 | 9 | public class Utils { 10 | private static final String CLDESC = "Ljava/lang/Class;"; 11 | 12 | private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte"); 13 | 14 | private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean"); 15 | 16 | private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short"); 17 | 18 | private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character"); 19 | 20 | private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer"); 21 | 22 | private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float"); 23 | 24 | private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long"); 25 | 26 | private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double"); 27 | 28 | private static final Type NUMBER_TYPE = Type.getObjectType("java/lang/Number"); 29 | 30 | private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object"); 31 | 32 | private static final Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); 33 | 34 | private static final Method CHAR_VALUE = Method.getMethod("char charValue()"); 35 | 36 | private static final Method INT_VALUE = Method.getMethod("int intValue()"); 37 | 38 | private static final Method FLOAT_VALUE = Method.getMethod("float floatValue()"); 39 | 40 | private static final Method LONG_VALUE = Method.getMethod("long longValue()"); 41 | 42 | private static final Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); 43 | 44 | private static Type getBoxedType(final Type type) { 45 | switch (type.getSort()) { 46 | case Type.BYTE: 47 | return BYTE_TYPE; 48 | case Type.BOOLEAN: 49 | return BOOLEAN_TYPE; 50 | case Type.SHORT: 51 | return SHORT_TYPE; 52 | case Type.CHAR: 53 | return CHARACTER_TYPE; 54 | case Type.INT: 55 | return INTEGER_TYPE; 56 | case Type.FLOAT: 57 | return FLOAT_TYPE; 58 | case Type.LONG: 59 | return LONG_TYPE; 60 | case Type.DOUBLE: 61 | return DOUBLE_TYPE; 62 | } 63 | return type; 64 | } 65 | 66 | public static void box(MethodVisitor mv, final Type type) { 67 | if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 68 | return; 69 | } 70 | 71 | Type boxed = getBoxedType(type); 72 | mv.visitTypeInsn(Opcodes.NEW, boxed.getInternalName()); 73 | if (type.getSize() == 2) { 74 | // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o 75 | mv.visitInsn(Opcodes.DUP_X2); 76 | mv.visitInsn(Opcodes.DUP_X2); 77 | mv.visitInsn(Opcodes.POP); 78 | } else { 79 | // p -> po -> opo -> oop -> o 80 | mv.visitInsn(Opcodes.DUP_X1); 81 | mv.visitInsn(Opcodes.SWAP); 82 | } 83 | mv.visitMethodInsn(Opcodes.INVOKESPECIAL, boxed.getInternalName(), "", "(" + type.getDescriptor() + ")V", false); 84 | 85 | } 86 | 87 | public static String ignorePattern = null; 88 | public static ConsumerUtils consumerUtils = new ConsumerUtils(); 89 | 90 | public static void unbox(MethodVisitor mv, final Type type) { 91 | Type t = NUMBER_TYPE; 92 | Method sig = null; 93 | switch (type.getSort()) { 94 | case Type.VOID: 95 | return; 96 | case Type.CHAR: 97 | t = CHARACTER_TYPE; 98 | sig = CHAR_VALUE; 99 | break; 100 | case Type.BOOLEAN: 101 | t = BOOLEAN_TYPE; 102 | sig = BOOLEAN_VALUE; 103 | break; 104 | case Type.DOUBLE: 105 | sig = DOUBLE_VALUE; 106 | break; 107 | case Type.FLOAT: 108 | sig = FLOAT_VALUE; 109 | break; 110 | case Type.LONG: 111 | sig = LONG_VALUE; 112 | break; 113 | case Type.INT: 114 | case Type.SHORT: 115 | case Type.BYTE: 116 | sig = INT_VALUE; 117 | } 118 | if (sig == null) { 119 | mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName()); 120 | } else { 121 | mv.visitTypeInsn(Opcodes.CHECKCAST, t.getInternalName()); 122 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, t.getInternalName(), sig.getName(), sig.getDescriptor(), false); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /vmvm/src/main/java/java/edu/columbia/cs/psl/vmvm/runtime/InterfaceReinitializer.java: -------------------------------------------------------------------------------- 1 | package java.edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | public abstract class InterfaceReinitializer { 4 | public static final String INTERNAL_NAME = "java/edu/columbia/cs/psl/vmvm/runtime/InterfaceReinitializer"; 5 | public abstract void __vmvmReClinit(); 6 | } 7 | -------------------------------------------------------------------------------- /vmvm/src/main/java/java/edu/columbia/cs/psl/vmvm/runtime/MutableInstance.java: -------------------------------------------------------------------------------- 1 | package java.edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import java.io.Serializable; 4 | 5 | public class MutableInstance implements Serializable { 6 | public static final String INTERNAL_NAME="java/edu/columbia/cs/psl/vmvm/runtime/MutableInstance"; 7 | public static final String DESC = "Ljava/edu/columbia/cs/psl/vmvm/runtime/MutableInstance;"; 8 | private Object inst; 9 | private Class type; 10 | public MutableInstance(Class type,Object o) 11 | { 12 | this.inst = o; 13 | this.type = type; 14 | } 15 | public MutableInstance(Class type) 16 | { 17 | this.type = type; 18 | } 19 | public Class getType() { 20 | return type; 21 | } 22 | public Object get() 23 | { 24 | return inst; 25 | } 26 | public void put(Object o) 27 | { 28 | inst = o; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vmvm/src/main/java/java/edu/columbia/cs/psl/vmvm/runtime/ReflectionWrapper.java: -------------------------------------------------------------------------------- 1 | package java.edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import edu.columbia.cs.psl.vmvm.runtime.VMVMClassFileTransformer; 4 | import edu.columbia.cs.psl.vmvm.runtime.inst.Constants; 5 | import sun.misc.Unsafe; 6 | 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Modifier; 11 | import java.util.ArrayList; 12 | 13 | public class ReflectionWrapper { 14 | 15 | private static Field getField(Class clazz, String name) throws NoSuchFieldException { 16 | return clazz.getField(name); 17 | } 18 | public static void putStaticField(Object value, Class clazz, String name) throws NoSuchFieldException { 19 | Field f = getField(clazz, name); 20 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 21 | u.putObject(u.staticFieldBase(f),u.staticFieldOffset(f), value); 22 | } 23 | public static void putStaticField(boolean value, Class clazz, String name) throws NoSuchFieldException { 24 | Field f = getField(clazz, name); 25 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 26 | u.putBoolean(u.staticFieldBase(f),u.staticFieldOffset(f), value); 27 | } 28 | public static void putStaticField(byte value, Class clazz, String name) throws NoSuchFieldException { 29 | Field f = getField(clazz, name); 30 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 31 | u.putByte(u.staticFieldBase(f),u.staticFieldOffset(f), value); 32 | } 33 | public static void putStaticField(char value, Class clazz, String name) throws NoSuchFieldException { 34 | Field f = getField(clazz, name); 35 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 36 | u.putChar(u.staticFieldBase(f),u.staticFieldOffset(f), value); 37 | } 38 | public static void putStaticField(int value, Class clazz, String name) throws NoSuchFieldException { 39 | Field f = getField(clazz, name); 40 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 41 | u.putInt(u.staticFieldBase(f),u.staticFieldOffset(f), value); 42 | } 43 | public static void putStaticField(short value, Class clazz, String name) throws NoSuchFieldException { 44 | Field f = getField(clazz, name); 45 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 46 | u.putShort(u.staticFieldBase(f),u.staticFieldOffset(f), value); 47 | } 48 | public static void putStaticField(long value, Class clazz, String name) throws NoSuchFieldException { 49 | Field f = getField(clazz, name); 50 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 51 | u.putLong(u.staticFieldBase(f),u.staticFieldOffset(f), value); 52 | } 53 | public static void putStaticField(float value, Class clazz, String name) throws NoSuchFieldException { 54 | Field f = getField(clazz, name); 55 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 56 | u.putFloat(u.staticFieldBase(f),u.staticFieldOffset(f), value); 57 | } 58 | public static void putStaticField(double value, Class clazz, String name) throws NoSuchFieldException { 59 | Field f = getField(clazz, name); 60 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 61 | u.putDouble(u.staticFieldBase(f),u.staticFieldOffset(f), value); 62 | } 63 | 64 | 65 | public static Method[] getDeclaredMethods(Class clazz) { 66 | Method[] r = clazz.getDeclaredMethods(); 67 | if(VMVMClassFileTransformer.isIgnoredClass(clazz.getName())) 68 | return r; 69 | if(clazz.isInterface() || r.length == 0) 70 | return r; 71 | boolean found = false; 72 | for (Class c : clazz.getInterfaces()) 73 | if (c.equals(VMVMInstrumented.class)) 74 | found = true; 75 | if (!found) 76 | return r; 77 | Method[] ret = new Method[r.length - 1]; 78 | int j = 0; 79 | for (int i = 0; i < r.length; i++) { 80 | if (r[i].getName().equals("__vmvmReClinit")) 81 | continue; 82 | ret[j] = r[i]; 83 | j++; 84 | } 85 | return ret; 86 | } 87 | public static Class[] getInterfaces(Class clazz) { 88 | Class[] ret = clazz.getInterfaces(); 89 | ArrayList _ret = new ArrayList(ret.length); 90 | for (int i = 0; i < ret.length; i++) { 91 | if (ret[i] == VMVMInstrumented.class) 92 | continue; 93 | _ret.add(ret[i]); 94 | } 95 | return _ret.toArray(new Class[_ret.size()]); 96 | } 97 | public static Class getType(Field f) throws IllegalArgumentException, IllegalAccessException 98 | { 99 | Class ret = f.getType(); 100 | if(ret == MutableInstance.class) 101 | return ((MutableInstance)f.get(null)).getType(); 102 | return ret; 103 | } 104 | public static Method[] getMethods(Class clazz) { 105 | Method[] r = clazz.getMethods(); 106 | if(VMVMClassFileTransformer.isIgnoredClass(clazz.getName())) 107 | return r; 108 | if(clazz.isInterface() || r.length == 0) 109 | return r; 110 | boolean found = false; 111 | for (Class c : clazz.getInterfaces()) 112 | if (c.equals(VMVMInstrumented.class)) 113 | found = true; 114 | if (!found) 115 | return r; 116 | Method[] ret = new Method[r.length - 1]; 117 | int j = 0; 118 | for (int i = 0; i < r.length; i++) { 119 | if (r[i].getName().equals("__vmvmReClinit")) 120 | continue; 121 | ret[j] = r[i]; 122 | j++; 123 | } 124 | return ret; 125 | } 126 | 127 | public static void set(Field f, Object owner, Object val) throws IllegalArgumentException, IllegalAccessException { 128 | tryToInit(f.getDeclaringClass()); 129 | f.setAccessible(true); 130 | if (f.getType() == MutableInstance.class) { 131 | ((MutableInstance) f.get(owner)).put(val); 132 | } else 133 | f.set(owner, val); 134 | } 135 | public static void setBoolean(Field f, Object owner, boolean val) throws IllegalArgumentException, IllegalAccessException { 136 | tryToInit(f.getDeclaringClass()); 137 | f.setAccessible(true); 138 | if (f.getType() == MutableInstance.class) { 139 | ((MutableInstance) f.get(owner)).put(val); 140 | } else 141 | f.setBoolean(owner, val); 142 | } 143 | public static void setByte(Field f, Object owner, byte val) throws IllegalArgumentException, IllegalAccessException { 144 | tryToInit(f.getDeclaringClass()); 145 | f.setAccessible(true); 146 | if (f.getType() == MutableInstance.class) { 147 | ((MutableInstance) f.get(owner)).put(val); 148 | } else 149 | f.setByte(owner, val); 150 | } 151 | public static void setChar(Field f, Object owner, char val) throws IllegalArgumentException, IllegalAccessException { 152 | tryToInit(f.getDeclaringClass()); 153 | f.setAccessible(true); 154 | if (f.getType() == MutableInstance.class) { 155 | ((MutableInstance) f.get(owner)).put(val); 156 | } else 157 | f.setChar(owner, val); 158 | } 159 | public static void setDouble(Field f, Object owner, double val) throws IllegalArgumentException, IllegalAccessException { 160 | tryToInit(f.getDeclaringClass()); 161 | f.setAccessible(true); 162 | if (f.getType() == MutableInstance.class) { 163 | ((MutableInstance) f.get(owner)).put(val); 164 | } else 165 | f.setDouble(owner, val); 166 | } 167 | public static void setInt(Field f, Object owner, int val) throws IllegalArgumentException, IllegalAccessException { 168 | tryToInit(f.getDeclaringClass()); 169 | f.setAccessible(true); 170 | if (f.getType() == MutableInstance.class) { 171 | ((MutableInstance) f.get(owner)).put(val); 172 | } else 173 | f.setInt(owner, val); 174 | } 175 | public static void setFloat(Field f, Object owner, float val) throws IllegalArgumentException, IllegalAccessException { 176 | tryToInit(f.getDeclaringClass()); 177 | f.setAccessible(true); 178 | if (f.getType() == MutableInstance.class) { 179 | ((MutableInstance) f.get(owner)).put(val); 180 | } else 181 | f.setFloat(owner, val); 182 | } 183 | public static void setLong(Field f, Object owner, long val) throws IllegalArgumentException, IllegalAccessException { 184 | tryToInit(f.getDeclaringClass()); 185 | f.setAccessible(true); 186 | if (f.getType() == MutableInstance.class) { 187 | ((MutableInstance) f.get(owner)).put(val); 188 | } else 189 | f.setLong(owner, val); 190 | } 191 | 192 | 193 | public static boolean getBoolean(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 194 | tryToInit(f.getDeclaringClass()); 195 | f.setAccessible(true); 196 | if (f.getType() == MutableInstance.class) 197 | return ((Boolean) ((MutableInstance) f.get(owner)).get()); 198 | return f.getBoolean(owner); 199 | } 200 | public static byte getByte(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 201 | tryToInit(f.getDeclaringClass()); 202 | f.setAccessible(true); 203 | if (f.getType() == MutableInstance.class) 204 | return ((Byte) ((MutableInstance) f.get(owner)).get()); 205 | return f.getByte(owner); 206 | } 207 | public static char getChar(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 208 | tryToInit(f.getDeclaringClass()); 209 | f.setAccessible(true); 210 | if (f.getType() == MutableInstance.class) 211 | return ((Character) ((MutableInstance) f.get(owner)).get()); 212 | return f.getChar(owner); 213 | } 214 | public static double getDouble(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 215 | tryToInit(f.getDeclaringClass()); 216 | f.setAccessible(true); 217 | if (f.getType() == MutableInstance.class) 218 | return ((Double) ((MutableInstance) f.get(owner)).get()); 219 | return f.getDouble(owner); 220 | } 221 | public static float getFloat(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 222 | tryToInit(f.getDeclaringClass()); 223 | f.setAccessible(true); 224 | if (f.getType() == MutableInstance.class) 225 | return ((Float) ((MutableInstance) f.get(owner)).get()); 226 | return f.getFloat(owner); 227 | } 228 | public static int getInt(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 229 | tryToInit(f.getDeclaringClass()); 230 | if (f.getType() == MutableInstance.class) 231 | return ((Integer) ((MutableInstance) f.get(owner)).get()); 232 | return f.getInt(owner); 233 | } 234 | public static long getLong(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 235 | tryToInit(f.getDeclaringClass()); 236 | if (f.getType() == MutableInstance.class) 237 | return ((Long) ((MutableInstance) f.get(owner)).get()); 238 | return f.getLong(owner); 239 | } 240 | public static Object get(Field f, Object owner) throws IllegalArgumentException, IllegalAccessException { 241 | tryToInit(f.getDeclaringClass()); 242 | f.setAccessible(true); 243 | Object ret = f.get(owner); 244 | if (ret instanceof MutableInstance) 245 | return ((MutableInstance) ret).get(); 246 | return ret; 247 | } 248 | 249 | public static Field[] getDeclaredFields(Class clazz) { 250 | Field[] r = clazz.getDeclaredFields(); 251 | ArrayList ret = new ArrayList<>(r.length); 252 | for (Field f : r) { 253 | if (!f.getName().startsWith("_vmvm") && !f.getName().endsWith("VMVM_CLASSES_TO_CHECK") && !f.getName().equals("VMVM_RESET_IN_PROGRESS") && !f.getName().equals("VMVM_NEEDS_RESET") 254 | && !f.getName().equals("$$VMVM_RESETTER")) 255 | ret.add(f); 256 | } 257 | r = new Field[ret.size()]; 258 | r = ret.toArray(r); 259 | return r; 260 | } 261 | 262 | public static Field[] getFields(Class clazz) { 263 | Field[] r = clazz.getFields(); 264 | ArrayList ret = new ArrayList<>(r.length); 265 | for (Field f : r) { 266 | if (!f.getName().startsWith("_vmvm") && !f.getName().endsWith("VMVM_CLASSES_TO_CHECK") && !f.getName().equals("VMVM_RESET_IN_PROGRESS") && !f.getName().equals("VMVM_NEEDS_RESET") 267 | && !f.getName().equals("$$VMVM_RESETTER")) 268 | ret.add(f); 269 | } 270 | r = new Field[ret.size()]; 271 | r = ret.toArray(r); 272 | return r; 273 | } 274 | 275 | public static Class forName(String name, ClassLoader loader) throws ClassNotFoundException { 276 | Class ret = Class.forName(name, true, loader); 277 | tryToInit(ret); 278 | return ret; 279 | } 280 | 281 | public static Class preNewInstance(Class clazz) throws InstantiationException, IllegalAccessException { 282 | tryToInit(clazz); 283 | return clazz; 284 | } 285 | 286 | public static Class forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException { 287 | Class ret = Class.forName(name, initialize, loader); 288 | if (initialize) { 289 | tryToInit(ret); 290 | } 291 | return ret; 292 | } 293 | 294 | public static Object invoke(Method m, Object owner, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 295 | if (Modifier.isStatic(m.getModifiers())) 296 | tryToInit(m.getDeclaringClass()); 297 | if (!m.isAccessible()) 298 | m.setAccessible(true); 299 | return m.invoke(owner, args); 300 | } 301 | 302 | public static int getModifiers(Class c) { 303 | // VMVMClassFileTransformer.ensureInit(); 304 | int ret = c.getModifiers(); 305 | // if(Instrumenter.finalClasses.contains(c.getName().replace(".", "/"))) 306 | // ret = ret | Modifier.FINAL; 307 | return ret; 308 | } 309 | 310 | public static int getModifiers(Method m) { 311 | // VMVMClassFileTransformer.ensureInit(); 312 | int ret = m.getModifiers(); 313 | // if(Instrumenter.finalMethods.contains(m.getDeclaringClass().getName().replace(".", "/") + "."+Type.getMethodDescriptor(m))) 314 | // ret = ret | Modifier.FINAL; 315 | return ret; 316 | } 317 | 318 | public static int getModifiers(Field f) { 319 | // VMVMClassFileTransformer.ensureInit(); 320 | int ret = f.getModifiers(); 321 | // if(Instrumenter.finalFields.contains(f.getDeclaringClass().getName().replace(".", "/") + "."+Type.getDescriptor(f.getType()))) 322 | // ret = ret | Modifier.FINAL; 323 | return ret; 324 | } 325 | 326 | public static void tryToInit(Class clazz) { 327 | // if(inited.contains(clazz)) 328 | // return; 329 | // inited.add(clazz); 330 | // synchronized (clazz) { 331 | if(clazz.isArray()) 332 | clazz = clazz.getComponentType(); 333 | if(VMVMClassFileTransformer.isIgnoredClass(clazz.getName().replace('.','/'))) 334 | return; 335 | try { 336 | boolean val = clazz.getField(Constants.VMVM_NEEDS_RESET).getBoolean(null); 337 | if (val) { 338 | InterfaceReinitializer resetter = (InterfaceReinitializer) clazz.getField(Constants.VMVM_RESET_FIELD).get(null); 339 | resetter.__vmvmReClinit(); 340 | } 341 | } catch (Throwable ex) { 342 | if (!(ex instanceof NoSuchFieldException)) { 343 | ex.printStackTrace(); 344 | System.err.println("Error on " + clazz); 345 | } 346 | 347 | } 348 | // } 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /vmvm/src/main/java/java/edu/columbia/cs/psl/vmvm/runtime/Reinitializer.java: -------------------------------------------------------------------------------- 1 | package java.edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | import edu.columbia.cs.psl.vmvm.runtime.VMVMClassFileTransformer; 4 | import edu.columbia.cs.psl.vmvm.runtime.inst.Constants; 5 | import edu.columbia.cs.psl.vmvm.runtime.inst.Utils; 6 | import sun.misc.Unsafe; 7 | 8 | import javax.management.MBeanServer; 9 | import javax.management.MBeanServerFactory; 10 | import javax.management.ObjectName; 11 | import java.lang.instrument.Instrumentation; 12 | import java.lang.management.ManagementFactory; 13 | import java.lang.ref.WeakReference; 14 | import java.lang.reflect.Field; 15 | import java.lang.reflect.Method; 16 | import java.net.URL; 17 | import java.util.*; 18 | 19 | 20 | public final class Reinitializer { 21 | public static final String INTERNAL_NAME = "java/edu/columbia/cs/psl/vmvm/runtime/Reinitializer"; 22 | 23 | public static Instrumentation inst; 24 | private static final boolean DEBUG = System.getenv("DEBUG") != null; 25 | 26 | static LinkedList> classesToReinit = new LinkedList>(); 27 | public static HashSet classesNotYetReinitialized = new HashSet(); 28 | 29 | 30 | public static final void logMessage(String s) { 31 | System.err.println(s + ": " + Thread.currentThread().getName()); 32 | } 33 | 34 | static HashSet ignored = new HashSet<>(); 35 | 36 | static String lastTestClass; 37 | public static void newTestClassHit(Class c){ 38 | newTestClassHit(c.getName()); 39 | } 40 | public static void newTestClassHit(String testClassName){ 41 | if (lastTestClass != null && !lastTestClass.equals(testClassName)) { 42 | Reinitializer.markAllClassesForReinit(); 43 | } 44 | lastTestClass = testClassName; 45 | } 46 | 47 | public static void deleteOnExitHook(){ 48 | try { 49 | Class c = Class.forName("java.io.DeleteOnExitHook"); 50 | Method m = c.getDeclaredMethod("runHooks"); 51 | m.setAccessible(true); 52 | m.invoke(null); 53 | Field f = c.getDeclaredField("files"); 54 | f.setAccessible(true); 55 | f.set(null, new LinkedHashSet()); 56 | } catch(Throwable t){ 57 | t.printStackTrace(); 58 | } 59 | } 60 | public static synchronized final void markAllClassesForReinit() { 61 | // long start = System.currentTimeMillis(); 62 | // System.err.println("Start MCR "); 63 | // ClassDefinition[] toReinit = new ClassDefinition[classesToReinit.size()]; 64 | resetInternalStatics(); 65 | 66 | synchronized (shutdownHooks) { 67 | for (Thread t : shutdownHooks) { 68 | Runtime.getRuntime().removeShutdownHook(t); 69 | } 70 | shutdownHooks.clear(); 71 | } 72 | deleteOnExitHook(); 73 | try { 74 | ArrayList mbeanServers = MBeanServerFactory.findMBeanServer(null); 75 | if (mbeanServers != null && mbeanServers.size() > 0) { 76 | for (MBeanServer server : mbeanServers) { 77 | // System.out.println("Releasing server " + server); 78 | MBeanServerFactory.releaseMBeanServer(server); 79 | } 80 | } 81 | mbeanServers = null; 82 | MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 83 | if (server.getMBeanCount() > 0) { 84 | Set onames = server.queryNames(null, null); 85 | for (ObjectName name : onames) 86 | try { 87 | server.unregisterMBean(name); 88 | } catch (Throwable e) { 89 | } 90 | } 91 | server = null; 92 | } catch (Throwable t) { 93 | //nop 94 | } 95 | 96 | for (String s : properties.keySet()) { 97 | // System.out.println("Reseting " + s + " from <" + System.getProperty(s) + "> to <" + properties.get(s) + ">"); 98 | if (properties.get(s) != null) 99 | System.setProperty(s, properties.get(s)); 100 | else 101 | System.clearProperty(s); 102 | } 103 | properties.clear(); 104 | LinkedList> toReinit = classesToReinit; 105 | classesToReinit = new LinkedList>(); 106 | classesNotYetReinitialized.clear(); 107 | for (WeakReference w : toReinit) { 108 | if (w.get() != null) { 109 | Class c = w.get(); 110 | if(ignored.contains(c)) 111 | continue; 112 | if(Utils.consumerUtils.isIgnoredClass(c.getName().replace('.','/'))) 113 | { 114 | ignored.add(c); 115 | continue; 116 | } 117 | if(DEBUG) 118 | System.out.println("Reinit: " + c.getName()); 119 | classesNotYetReinitialized.add(c.getName()); 120 | try { 121 | Field f = c.getField(Constants.VMVM_NEEDS_RESET); 122 | Unsafe u = VMVMClassFileTransformer.getUnsafe(); 123 | u.putBoolean(u.staticFieldBase(f), u.staticFieldOffset(f), true); 124 | } catch (IllegalArgumentException e) { 125 | e.printStackTrace(); 126 | } catch (NoSuchFieldException e) { 127 | System.err.println("On " + c); 128 | e.printStackTrace(); 129 | } catch (SecurityException e) { 130 | e.printStackTrace(); 131 | } 132 | 133 | } 134 | } 135 | Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); 136 | 137 | } 138 | 139 | private static HashSet shutdownHooks = new HashSet(); 140 | 141 | public static void addShutdownHook(Runtime r, Thread t) { 142 | synchronized (shutdownHooks) { 143 | r.addShutdownHook(t); 144 | shutdownHooks.add(t); 145 | } 146 | } 147 | 148 | public static final void fixEnum(Class c) { 149 | // if (VMVMClassFileTransformer.DEBUG) 150 | // System.out.println("Fixup enum " + c); 151 | try { 152 | Field f = Class.class.getDeclaredField("enumConstants"); 153 | f.setAccessible(true); 154 | f.set(c, null); 155 | f = Class.class.getDeclaredField("enumConstantDirectory"); 156 | f.setAccessible(true); 157 | f.set(c, null); 158 | } catch (Throwable t) { 159 | t.printStackTrace(); 160 | } 161 | } 162 | 163 | public static final void reinitCalled(Class c) { 164 | // System.err.println("Reinit: " + c); 165 | classesNotYetReinitialized.remove(c.getName()); 166 | classesToReinit.add(new WeakReference(c)); 167 | } 168 | 169 | public static final InterfaceReinitializer clinitCalled(Class c) { 170 | // if (VMVMClassFileTransformer.DEBUG) 171 | // System.out.println("CLinit called " + c.clazz + " in " + Thread.currentThread().getName()); 172 | classesToReinit.add(new WeakReference(c)); 173 | //TODO create the anonymous class here 174 | 175 | Class resetter = VMVMClassFileTransformer.generateResetter(c); 176 | try { 177 | InterfaceReinitializer ret = (InterfaceReinitializer) resetter.newInstance(); 178 | ret.__vmvmReClinit(); 179 | return ret; 180 | } catch (InstantiationException e) { 181 | e.printStackTrace(); 182 | } catch (IllegalAccessException e) { 183 | e.printStackTrace(); 184 | } 185 | return null; 186 | } 187 | 188 | public static Class lookupInterfaceClass(String name) { 189 | try { 190 | Class ret = VMVMClassFileTransformer.cl.loadClass(name.replace("/", ".")); 191 | if (ret == null) 192 | throw new IllegalArgumentException("Cant find interface resetter for " + name); 193 | return ret; 194 | } catch (Throwable t) { 195 | t.printStackTrace(); 196 | return null; 197 | } 198 | } 199 | 200 | private static Field URLStreamHandlerField; 201 | 202 | private static void resetInternalStatics() { 203 | if (URLStreamHandlerField == null) { 204 | try { 205 | URLStreamHandlerField = URL.class.getDeclaredField("factory"); 206 | URLStreamHandlerField.setAccessible(true); 207 | } catch (NoSuchFieldException e) { 208 | } catch (SecurityException e) { 209 | } 210 | } 211 | try { 212 | URLStreamHandlerField.set(null, null); 213 | } catch (Throwable t) { 214 | } 215 | 216 | if (logsUsed[44]) { 217 | try { 218 | javax.security.auth.Policy.setPolicy((javax.security.auth.Policy) loggedValues[44]); 219 | } catch (Exception ex) { 220 | ex.printStackTrace(); 221 | } 222 | logsUsed[44] = false; 223 | loggedValues[44] = null; 224 | } 225 | if (logsUsed[13]) { 226 | try { 227 | java.lang.Thread.setDefaultUncaughtExceptionHandler((java.lang.Thread.UncaughtExceptionHandler) loggedValues[13]); 228 | } catch (Exception ex) { 229 | ex.printStackTrace(); 230 | } 231 | logsUsed[13] = false; 232 | loggedValues[13] = null; 233 | } 234 | if (logsUsed[17]) { 235 | try { 236 | java.net.URLConnection.setContentHandlerFactory((java.net.ContentHandlerFactory) loggedValues[17]); 237 | } catch (Exception ex) { 238 | ex.printStackTrace(); 239 | } 240 | logsUsed[17] = false; 241 | loggedValues[17] = null; 242 | } 243 | if (logsUsed[18]) { 244 | try { 245 | java.net.URLConnection.setFileNameMap((java.net.FileNameMap) loggedValues[18]); 246 | } catch (Exception ex) { 247 | ex.printStackTrace(); 248 | } 249 | logsUsed[18] = false; 250 | loggedValues[18] = null; 251 | } 252 | if (logsUsed[19]) { 253 | try { 254 | java.net.URLConnection.setDefaultAllowUserInteraction((boolean) loggedValues[19]); 255 | } catch (Exception ex) { 256 | ex.printStackTrace(); 257 | } 258 | logsUsed[19] = false; 259 | loggedValues[19] = null; 260 | } 261 | if (logsUsed[20]) {//try{ 262 | //java.net.URLConnection.setDefaultRequestProperty(()loggedValues[20]);}catch(Exception ex){ex.printStackTrace();} 263 | logsUsed[20] = false; 264 | loggedValues[20] = null; 265 | } 266 | if (logsUsed[16]) { 267 | try { 268 | java.net.ResponseCache.setDefault((java.net.ResponseCache) loggedValues[16]); 269 | } catch (Exception ex) { 270 | ex.printStackTrace(); 271 | } 272 | logsUsed[16] = false; 273 | loggedValues[16] = null; 274 | } 275 | if (logsUsed[37]) { 276 | try { 277 | javax.imageio.ImageIO.setUseCache((boolean) loggedValues[37]); 278 | } catch (Exception ex) { 279 | ex.printStackTrace(); 280 | } 281 | logsUsed[37] = false; 282 | loggedValues[37] = null; 283 | } 284 | if (logsUsed[38]) { 285 | try { 286 | javax.imageio.ImageIO.setCacheDirectory((java.io.File) loggedValues[38]); 287 | } catch (Exception ex) { 288 | ex.printStackTrace(); 289 | } 290 | logsUsed[38] = false; 291 | loggedValues[38] = null; 292 | } 293 | if (logsUsed[35]) { 294 | try { 295 | javax.activation.CommandMap.setDefaultCommandMap((javax.activation.CommandMap) loggedValues[35]); 296 | } catch (Exception ex) { 297 | ex.printStackTrace(); 298 | } 299 | logsUsed[35] = false; 300 | loggedValues[35] = null; 301 | } 302 | if (logsUsed[63]) { 303 | try { 304 | javax.swing.plaf.synth.SynthLookAndFeel.setStyleFactory((javax.swing.plaf.synth.SynthStyleFactory) loggedValues[63]); 305 | } catch (Exception ex) { 306 | ex.printStackTrace(); 307 | } 308 | logsUsed[63] = false; 309 | loggedValues[63] = null; 310 | } 311 | if (logsUsed[55]) { 312 | try { 313 | javax.swing.Timer.setLogTimers((boolean) loggedValues[55]); 314 | } catch (Exception ex) { 315 | ex.printStackTrace(); 316 | } 317 | logsUsed[55] = false; 318 | loggedValues[55] = null; 319 | } 320 | if (logsUsed[43]) { 321 | try { 322 | javax.net.ssl.SSLContext.setDefault((javax.net.ssl.SSLContext) loggedValues[43]); 323 | } catch (Exception ex) { 324 | ex.printStackTrace(); 325 | } 326 | logsUsed[43] = false; 327 | loggedValues[43] = null; 328 | } 329 | if (logsUsed[21]) { 330 | try { 331 | java.rmi.activation.ActivationGroup.setSystem((java.rmi.activation.ActivationSystem) loggedValues[21]); 332 | } catch (Exception ex) { 333 | ex.printStackTrace(); 334 | } 335 | logsUsed[21] = false; 336 | loggedValues[21] = null; 337 | } 338 | if (logsUsed[41]) { 339 | try { 340 | javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory((javax.net.ssl.SSLSocketFactory) loggedValues[41]); 341 | } catch (Exception ex) { 342 | ex.printStackTrace(); 343 | } 344 | logsUsed[41] = false; 345 | loggedValues[41] = null; 346 | } 347 | if (logsUsed[42]) { 348 | try { 349 | javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier((javax.net.ssl.HostnameVerifier) loggedValues[42]); 350 | } catch (Exception ex) { 351 | ex.printStackTrace(); 352 | } 353 | logsUsed[42] = false; 354 | loggedValues[42] = null; 355 | } 356 | if (logsUsed[54]) { 357 | try { 358 | javax.swing.PopupFactory.setSharedInstance((javax.swing.PopupFactory) loggedValues[54]); 359 | } catch (Exception ex) { 360 | ex.printStackTrace(); 361 | } 362 | logsUsed[54] = false; 363 | loggedValues[54] = null; 364 | } 365 | if (logsUsed[51]) { 366 | try { 367 | javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled((boolean) loggedValues[51]); 368 | } catch (Exception ex) { 369 | ex.printStackTrace(); 370 | } 371 | logsUsed[51] = false; 372 | loggedValues[51] = null; 373 | } 374 | if (logsUsed[14]) { 375 | try { 376 | java.net.CookieHandler.setDefault((java.net.CookieHandler) loggedValues[14]); 377 | } catch (Exception ex) { 378 | ex.printStackTrace(); 379 | } 380 | logsUsed[14] = false; 381 | loggedValues[14] = null; 382 | } 383 | if (logsUsed[46]) { 384 | try { 385 | javax.sql.rowset.spi.SyncFactory.setLogger((java.util.logging.Logger) loggedValues[46]); 386 | } catch (Exception ex) { 387 | ex.printStackTrace(); 388 | } 389 | logsUsed[46] = false; 390 | loggedValues[46] = null; 391 | } 392 | if (logsUsed[47]) { 393 | try { 394 | javax.sql.rowset.spi.SyncFactory.setJNDIContext((javax.naming.Context) loggedValues[47]); 395 | } catch (Exception ex) { 396 | ex.printStackTrace(); 397 | } 398 | logsUsed[47] = false; 399 | loggedValues[47] = null; 400 | } 401 | if (logsUsed[67]) { 402 | try { 403 | java.net.Authenticator.setDefault((java.net.Authenticator) loggedValues[67]); 404 | } catch (Exception ex) { 405 | ex.printStackTrace(); 406 | } 407 | logsUsed[67] = false; 408 | loggedValues[67] = null; 409 | } 410 | if (logsUsed[53]) { 411 | try { 412 | javax.swing.LayoutStyle.setInstance((javax.swing.LayoutStyle) loggedValues[53]); 413 | } catch (Exception ex) { 414 | ex.printStackTrace(); 415 | } 416 | logsUsed[53] = false; 417 | loggedValues[53] = null; 418 | } 419 | if (logsUsed[39]) { 420 | try { 421 | javax.naming.spi.NamingManager.setInitialContextFactoryBuilder((javax.naming.spi.InitialContextFactoryBuilder) loggedValues[39]); 422 | } catch (Exception ex) { 423 | ex.printStackTrace(); 424 | } 425 | logsUsed[39] = false; 426 | loggedValues[39] = null; 427 | } 428 | if (logsUsed[40]) { 429 | try { 430 | javax.naming.spi.NamingManager.setObjectFactoryBuilder((javax.naming.spi.ObjectFactoryBuilder) loggedValues[40]); 431 | } catch (Exception ex) { 432 | ex.printStackTrace(); 433 | } 434 | logsUsed[40] = false; 435 | loggedValues[40] = null; 436 | } 437 | if (logsUsed[45]) { 438 | try { 439 | javax.security.auth.login.Configuration.setConfiguration((javax.security.auth.login.Configuration) loggedValues[45]); 440 | } catch (Exception ex) { 441 | ex.printStackTrace(); 442 | } 443 | logsUsed[45] = false; 444 | loggedValues[45] = null; 445 | } 446 | if (logsUsed[65]) { 447 | try { 448 | javax.swing.JDialog.setDefaultLookAndFeelDecorated((boolean) loggedValues[65]); 449 | } catch (Exception ex) { 450 | ex.printStackTrace(); 451 | } 452 | logsUsed[65] = false; 453 | loggedValues[65] = null; 454 | } 455 | if (logsUsed[30]) { 456 | try { 457 | java.sql.DriverManager.setLoginTimeout((int) loggedValues[30]); 458 | } catch (Exception ex) { 459 | ex.printStackTrace(); 460 | } 461 | logsUsed[30] = false; 462 | loggedValues[30] = null; 463 | } 464 | if (logsUsed[32]) { 465 | try { 466 | java.sql.DriverManager.setLogWriter((java.io.PrintWriter) loggedValues[32]); 467 | } catch (Exception ex) { 468 | ex.printStackTrace(); 469 | } 470 | logsUsed[32] = false; 471 | loggedValues[32] = null; 472 | } 473 | if (logsUsed[31]) { 474 | try { 475 | java.sql.DriverManager.setLogStream((java.io.PrintStream) loggedValues[31]); 476 | } catch (Exception ex) { 477 | ex.printStackTrace(); 478 | } 479 | logsUsed[31] = false; 480 | loggedValues[31] = null; 481 | } 482 | if (logsUsed[50]) { 483 | try { 484 | javax.swing.JOptionPane.setRootFrame((java.awt.Frame) loggedValues[50]); 485 | } catch (Exception ex) { 486 | ex.printStackTrace(); 487 | } 488 | logsUsed[50] = false; 489 | loggedValues[50] = null; 490 | } 491 | if (logsUsed[49]) { 492 | try { 493 | javax.swing.JComponent.setDefaultLocale((java.util.Locale) loggedValues[49]); 494 | } catch (Exception ex) { 495 | ex.printStackTrace(); 496 | } 497 | logsUsed[49] = false; 498 | loggedValues[49] = null; 499 | } 500 | if (logsUsed[3]) {//try{ 501 | //java.awt.AWTEventMulticaster..(()loggedValues[3]);}catch(Exception ex){ex.printStackTrace();} 502 | logsUsed[3] = false; 503 | loggedValues[3] = null; 504 | } 505 | if (logsUsed[15]) { 506 | try { 507 | java.net.ProxySelector.setDefault((java.net.ProxySelector) loggedValues[15]); 508 | } catch (Exception ex) { 509 | ex.printStackTrace(); 510 | } 511 | logsUsed[15] = false; 512 | loggedValues[15] = null; 513 | } 514 | if (logsUsed[5]) { 515 | try { 516 | java.beans.Introspector.setBeanInfoSearchPath((java.lang.String[]) loggedValues[5]); 517 | } catch (Exception ex) { 518 | ex.printStackTrace(); 519 | } 520 | logsUsed[5] = false; 521 | loggedValues[5] = null; 522 | } 523 | if (logsUsed[36]) { 524 | try { 525 | javax.activation.FileTypeMap.setDefaultFileTypeMap((javax.activation.FileTypeMap) loggedValues[36]); 526 | } catch (Exception ex) { 527 | ex.printStackTrace(); 528 | } 529 | logsUsed[36] = false; 530 | loggedValues[36] = null; 531 | } 532 | if (logsUsed[29]) {//try{ 533 | //java.security.Security.setProperty(()loggedValues[29]);}catch(Exception ex){ex.printStackTrace();} 534 | logsUsed[29] = false; 535 | loggedValues[29] = null; 536 | } 537 | if (logsUsed[4]) { 538 | try { 539 | java.awt.KeyboardFocusManager.setCurrentKeyboardFocusManager((java.awt.KeyboardFocusManager) loggedValues[4]); 540 | } catch (Exception ex) { 541 | ex.printStackTrace(); 542 | } 543 | logsUsed[4] = false; 544 | loggedValues[4] = null; 545 | } 546 | if (logsUsed[26]) { 547 | try { 548 | java.security.Policy.setPolicy((java.security.Policy) loggedValues[26]); 549 | } catch (Exception ex) { 550 | ex.printStackTrace(); 551 | } 552 | logsUsed[26] = false; 553 | loggedValues[26] = null; 554 | } 555 | if (logsUsed[23]) { 556 | try { 557 | java.rmi.server.RMISocketFactory.setFailureHandler((java.rmi.server.RMIFailureHandler) loggedValues[23]); 558 | } catch (Exception ex) { 559 | ex.printStackTrace(); 560 | } 561 | logsUsed[23] = false; 562 | loggedValues[23] = null; 563 | } 564 | if (logsUsed[24]) { 565 | try { 566 | java.rmi.server.RMISocketFactory.setSocketFactory((java.rmi.server.RMISocketFactory) loggedValues[24]); 567 | } catch (Exception ex) { 568 | ex.printStackTrace(); 569 | } 570 | logsUsed[24] = false; 571 | loggedValues[24] = null; 572 | } 573 | if (logsUsed[64]) { 574 | try { 575 | javax.swing.text.LayoutQueue.setDefaultQueue((javax.swing.text.LayoutQueue) loggedValues[64]); 576 | } catch (Exception ex) { 577 | ex.printStackTrace(); 578 | } 579 | logsUsed[64] = false; 580 | loggedValues[64] = null; 581 | } 582 | if (logsUsed[33]) { 583 | try { 584 | java.util.Locale.setDefault((java.util.Locale) loggedValues[33]); 585 | } catch (Exception ex) { 586 | ex.printStackTrace(); 587 | } 588 | logsUsed[33] = false; 589 | loggedValues[33] = null; 590 | } 591 | if (logsUsed[66]) { 592 | try { 593 | javax.swing.JFrame.setDefaultLookAndFeelDecorated((boolean) loggedValues[66]); 594 | } catch (Exception ex) { 595 | ex.printStackTrace(); 596 | } 597 | logsUsed[66] = false; 598 | loggedValues[66] = null; 599 | } 600 | if (logsUsed[7]) { 601 | try { 602 | java.lang.System.setOut((java.io.PrintStream) loggedValues[7]); 603 | } catch (Exception ex) { 604 | ex.printStackTrace(); 605 | } 606 | logsUsed[7] = false; 607 | loggedValues[7] = null; 608 | } 609 | if (logsUsed[8]) { 610 | try { 611 | java.lang.System.setIn((java.io.InputStream) loggedValues[8]); 612 | } catch (Exception ex) { 613 | ex.printStackTrace(); 614 | } 615 | logsUsed[8] = false; 616 | loggedValues[8] = null; 617 | } 618 | if (logsUsed[9]) { 619 | try { 620 | java.lang.System.setProperties((java.util.Properties) loggedValues[9]); 621 | } catch (Exception ex) { 622 | ex.printStackTrace(); 623 | } 624 | logsUsed[9] = false; 625 | loggedValues[9] = null; 626 | } 627 | if (logsUsed[10]) { 628 | try { 629 | java.lang.System.setSecurityManager((java.lang.SecurityManager) loggedValues[10]); 630 | } catch (Exception ex) { 631 | ex.printStackTrace(); 632 | } 633 | logsUsed[10] = false; 634 | loggedValues[10] = null; 635 | } 636 | if (logsUsed[11]) {//try{ 637 | //java.lang.System.setProperty(()loggedValues[11]);}catch(Exception ex){ex.printStackTrace();} 638 | logsUsed[11] = false; 639 | loggedValues[11] = null; 640 | } 641 | if (logsUsed[12]) { 642 | try { 643 | java.lang.System.setErr((java.io.PrintStream) loggedValues[12]); 644 | } catch (Exception ex) { 645 | ex.printStackTrace(); 646 | } 647 | logsUsed[12] = false; 648 | loggedValues[12] = null; 649 | } 650 | if (logsUsed[6]) { 651 | try { 652 | java.beans.PropertyEditorManager.setEditorSearchPath((java.lang.String[]) loggedValues[6]); 653 | } catch (Exception ex) { 654 | ex.printStackTrace(); 655 | } 656 | logsUsed[6] = false; 657 | loggedValues[6] = null; 658 | } 659 | if (logsUsed[62]) {//try{ 660 | //javax.swing.plaf.nimbus.EffectUtils.setPixels(()loggedValues[62]);}catch(Exception ex){ex.printStackTrace();} 661 | logsUsed[62] = false; 662 | loggedValues[62] = null; 663 | } 664 | if (logsUsed[34]) { 665 | try { 666 | java.util.TimeZone.setDefault((java.util.TimeZone) loggedValues[34]); 667 | } catch (Exception ex) { 668 | ex.printStackTrace(); 669 | } 670 | logsUsed[34] = false; 671 | loggedValues[34] = null; 672 | } 673 | if (logsUsed[61]) { 674 | try { 675 | javax.swing.UIManager.setInstalledLookAndFeels((javax.swing.UIManager.LookAndFeelInfo[]) loggedValues[61]); 676 | } catch (Exception ex) { 677 | ex.printStackTrace(); 678 | } 679 | logsUsed[61] = false; 680 | loggedValues[61] = null; 681 | } 682 | if (logsUsed[60]) { 683 | try { 684 | javax.swing.UIManager.setLookAndFeel((java.lang.String) loggedValues[60]); 685 | } catch (Exception ex) { 686 | ex.printStackTrace(); 687 | } 688 | logsUsed[60] = false; 689 | loggedValues[60] = null; 690 | } 691 | if (logsUsed[52]) {//try{ 692 | //javax.swing.KeyboardManager.setCurrentManager((javax.swing.KeyboardManager)loggedValues[52]);}catch(Exception ex){ex.printStackTrace();} 693 | logsUsed[52] = false; 694 | loggedValues[52] = null; 695 | } 696 | if (logsUsed[48]) { 697 | try { 698 | javax.swing.FocusManager.setCurrentManager((javax.swing.FocusManager) loggedValues[48]); 699 | } catch (Exception ex) { 700 | ex.printStackTrace(); 701 | } 702 | logsUsed[48] = false; 703 | loggedValues[48] = null; 704 | } 705 | if (logsUsed[22]) { 706 | try { 707 | java.rmi.server.LogStream.setDefaultStream((java.io.PrintStream) loggedValues[22]); 708 | } catch (Exception ex) { 709 | ex.printStackTrace(); 710 | } 711 | logsUsed[22] = false; 712 | loggedValues[22] = null; 713 | } 714 | if (logsUsed[25]) { 715 | try { 716 | java.rmi.server.RemoteServer.setLog((java.io.OutputStream) loggedValues[25]); 717 | } catch (Exception ex) { 718 | ex.printStackTrace(); 719 | } 720 | logsUsed[25] = false; 721 | loggedValues[25] = null; 722 | } 723 | 724 | if (logsUsed[1]) { 725 | loggedValues[1] = null; 726 | logsUsed[1] = false; 727 | } 728 | if (logsUsed[2]) { 729 | loggedValues[2] = null; 730 | logsUsed[2] = false; 731 | } 732 | if (logsUsed[27]) { 733 | loggedValues[27] = null; 734 | logsUsed[27] = false; 735 | } 736 | if (logsUsed[28]) { 737 | loggedValues[28] = null; 738 | logsUsed[28] = false; 739 | } 740 | if (logsUsed[56]) { 741 | for (WeakReference o : (LinkedList>) loggedValues[56]) 742 | if (!o.isEnqueued()) 743 | javax.swing.UIManager.removePropertyChangeListener((java.beans.PropertyChangeListener) o.get()); 744 | loggedValues[56] = null; 745 | logsUsed[56] = false; 746 | } 747 | if (logsUsed[57]) { 748 | for (WeakReference o : (LinkedList>) loggedValues[57]) 749 | if (!o.isEnqueued()) 750 | javax.swing.UIManager.removeAuxiliaryLookAndFeel((javax.swing.LookAndFeel) o.get()); 751 | loggedValues[57] = null; 752 | logsUsed[57] = false; 753 | } 754 | if (logsUsed[58]) { 755 | for (Object o : (LinkedList) loggedValues[58]) 756 | javax.swing.UIManager.addPropertyChangeListener((java.beans.PropertyChangeListener) o); 757 | loggedValues[58] = null; 758 | logsUsed[58] = false; 759 | } 760 | if (logsUsed[59]) { 761 | for (Object o : (LinkedList) loggedValues[59]) 762 | javax.swing.UIManager.addAuxiliaryLookAndFeel((javax.swing.LookAndFeel) o); 763 | loggedValues[59] = null; 764 | logsUsed[59] = false; 765 | } 766 | 767 | } 768 | 769 | public static void logStaticInternal(Object o, int i) { 770 | if (logsUsed[i]) 771 | return; 772 | logsUsed[i] = true; 773 | loggedValues[i] = o; 774 | } 775 | 776 | @SuppressWarnings("unchecked") 777 | public static void logStaticInternalAdd(Object o, int i) { 778 | if (!logsUsed[i]) 779 | loggedValues[i] = new LinkedList>(); 780 | logsUsed[i] = true; 781 | ((LinkedList>) loggedValues[i]).add(new WeakReference(o)); 782 | } 783 | 784 | public static void logStaticInternalRemove(Object o, int i) { 785 | if (!logsUsed[i]) 786 | loggedValues[i] = new LinkedList(); 787 | logsUsed[i] = true; 788 | ((LinkedList) loggedValues[i]).add(o); 789 | } 790 | 791 | public static String logAndSetProperty(String key, String value) { 792 | if (!properties.containsKey(key)) 793 | properties.put(key, System.getProperty(key)); 794 | return System.setProperty(key, value); 795 | } 796 | 797 | public static String logAndGetProperty(String key) { 798 | String ret = System.getProperty(key); 799 | //System.out.println("SYs prop " + key+"="+ret); 800 | return ret; 801 | } 802 | 803 | public static String logAndGetProperty(String key, String def) { 804 | String ret = System.getProperty(key, def); 805 | //System.out.println("SYs prop " + key+"="+ret +", def was " + def); 806 | return ret; 807 | } 808 | 809 | public static void logAndSetProperty(Properties values) { 810 | for (Object key : values.keySet()) { 811 | if (!properties.containsKey(key)) 812 | properties.put((String) key, System.getProperty((String) key)); 813 | } 814 | System.setProperties(values); 815 | } 816 | 817 | public static Object[] loggedValues = new Object[74]; 818 | public static boolean[] logsUsed = new boolean[74]; 819 | public static HashMap properties = new HashMap<>(); 820 | } 821 | -------------------------------------------------------------------------------- /vmvm/src/main/java/java/edu/columbia/cs/psl/vmvm/runtime/VMVMInstrumented.java: -------------------------------------------------------------------------------- 1 | package java.edu.columbia.cs.psl.vmvm.runtime; 2 | 3 | public interface VMVMInstrumented { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /vmvm/src/main/resources/java/edu/columbia/cs/psl/vmvm/runtime/ignored-clinits: -------------------------------------------------------------------------------- 1 | javax/xml/namespace/QName -------------------------------------------------------------------------------- /vmvm/src/main/resources/java/edu/columbia/cs/psl/vmvm/runtime/internal-statics: -------------------------------------------------------------------------------- 1 | java/awt/AWTEventMulticaster add remove . . 2 | java/awt/KeyboardFocusManager setCurrentKeyboardFocusManager getCurrentKeyboardFocusManager 3 | java/beans/Introspector setBeanInfoSearchPath getBeanInfo,getBeanInfoSearchPath 4 | java/beans/PropertyEditorManager setEditorSearchPath getEditorSearchPath 5 | java/lang/System setOut,setIn,setProperties,setSecurityManager,setProperty,setErr getenv,getSecurityManager,getProperty,getProperties 6 | java/lang/Thread setDefaultUncaughtExceptionHandler getDefaultUncaughtExceptionHandler,getAllStackTraces 7 | java/net/CookieHandler setDefault getDefault 8 | java/net/HttpURLConnection setFollowRedirects getFollowRedirects 9 | java/net/ProxySelector setDefault getDefault 10 | java/net/ResponseCache setDefault getDefault 11 | java/net/URLConnection setContentHandlerFactory,setFileNameMap,setDefaultAllowUserInteraction,setDefaultRequestProperty getDefaultRequestProperty,getDefaultAllowUserInteraction,getFileNameMap 12 | java/rmi/activation/ActivationGroup setSystem getSystem 13 | java/rmi/server/LogStream setDefaultStream getDefaultStream 14 | java/rmi/server/RMISocketFactory setFailureHandler,setSocketFactory getSocketFactory,getDefaultSocketFactory,getFailureHandler 15 | java/rmi/server/RemoteServer setLog getClientHost,getLog 16 | java/security/Policy setPolicy getPolicy,getInstance 17 | java/security/Security addProvider removeProvider setProperty getAlgorithmProperty,getProvider,getAlgorithms,getProperty,getProviders 18 | java/sql/DriverManager setLoginTimeout,setLogStream,setLogWriter getDriver,getDrivers,getLogWriter,getLoginTimeout,getLogStream,getConnection 19 | java/util/Locale setDefault getDefault,getAvailableLocales,getISOLanguages,getISOCountries 20 | java/util/TimeZone setDefault getTimeZone,getAvailableIDs,getDefault 21 | javax/activation/CommandMap setDefaultCommandMap getDefaultCommandMap 22 | javax/activation/FileTypeMap setDefaultFileTypeMap getDefaultFileTypeMap 23 | javax/imageio/ImageIO setUseCache,setCacheDirectory getWriterFileSuffixes,getReaderFormatNames,getImageWriters,getImageWritersBySuffix,getImageWritersByMIMEType,getReaderFileSuffixes,getImageWriter,getUseCache,getImageReadersBySuffix,getWriterMIMETypes,getImageReadersByMIMEType,getImageTranscoders,getImageReaders,getReaderMIMETypes,getImageReader,getCacheDirectory,getImageWritersByFormatName,getWriterFormatNames,getImageReadersByFormatName 24 | javax/naming/spi/NamingManager setInitialContextFactoryBuilder,setObjectFactoryBuilder getContinuationContext,getObjectInstance,getURLContext,getStateToBind,getInitialContext 25 | javax/net/ssl/HttpsURLConnection setDefaultSSLSocketFactory,setDefaultHostnameVerifier getDefaultSSLSocketFactory,getDefaultHostnameVerifier 26 | javax/net/ssl/SSLContext setDefault getDefault,getInstance 27 | javax/security/auth/Policy setPolicy getPolicy 28 | javax/security/auth/login/Configuration setConfiguration getConfiguration,getInstance 29 | javax/sql/rowset/spi/SyncFactory setLogger,setJNDIContext getSyncFactory,getLogger,getRegisteredProviders,getInstance 30 | javax/swing/FocusManager setCurrentManager getCurrentManager 31 | javax/swing/JComponent setDefaultLocale getDefaultLocale 32 | javax/swing/JOptionPane setRootFrame getDesktopPaneForComponent,getFrameForComponent,getRootFrame 33 | javax/swing/JPopupMenu setDefaultLightWeightPopupEnabled getDefaultLightWeightPopupEnabled 34 | javax/swing/KeyboardManager setCurrentManager getCurrentManager 35 | javax/swing/LayoutStyle setInstance getInstance 36 | javax/swing/PopupFactory setSharedInstance getSharedInstance 37 | javax/swing/Timer setLogTimers getLogTimers 38 | javax/swing/UIManager addPropertyChangeListener,addAuxiliaryLookAndFeel removePropertyChangeListener,removeAuxiliaryLookAndFeel setLookAndFeel,setInstalledLookAndFeels getDefaults,getPropertyChangeListeners,getInstalledLookAndFeels,getColor,get,getInt,getInsets,getBoolean,getAuxiliaryLookAndFeels,getBorder,getDimension,getLookAndFeelDefaults,getIcon,getFont,getLookAndFeel,getCrossPlatformLookAndFeelClassName,getString,getUI,getSystemLookAndFeelClassName 39 | javax/swing/plaf/nimbus/EffectUtils setPixels getPixels 40 | javax/swing/plaf/synth/SynthLookAndFeel setStyleFactory getStyleFactory,getRegion,getStyle 41 | javax/swing/text/LayoutQueue setDefaultQueue getDefaultQueue 42 | javax/swing/JDialog setDefaultLookAndFeelDecorated isDefaultLookAndFeelDecorated 43 | javax/swing/JFrame setDefaultLookAndFeelDecorated isDefaultLookAndFeelDecorated 44 | java/net/Authenticator setDefault null -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/EnumITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import static org.junit.Assert.assertSame; 4 | 5 | import org.junit.Test; 6 | 7 | import edu.columbia.cs.psl.test.vmvm.classes.EEnum; 8 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 9 | 10 | public class EnumITCase { 11 | @Test 12 | public void testValueOf() throws Exception { 13 | EEnum a = EEnum.A; 14 | Reinitializer.markAllClassesForReinit(); 15 | EEnum b = EEnum.A; 16 | System.out.println("Now assertsame"); 17 | assertSame(b,EEnum.valueOf("A")); 18 | } 19 | @Test 20 | public void testValues() throws Exception { 21 | EEnum a = EEnum.A; 22 | Reinitializer.markAllClassesForReinit(); 23 | EEnum b = EEnum.A; 24 | for(EEnum z : EEnum.values()) 25 | { 26 | if(z.getName().equals("A")) 27 | assertSame(b,z); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/EvilInterface.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import java.util.HashMap; 4 | 5 | public interface EvilInterface { 6 | public static final HashMap baz = new HashMap(); 7 | public void getBaz(); 8 | public static final long lon = 10; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/InternalStaticITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import static org.junit.Assert.assertSame; 4 | 5 | import java.util.Locale; 6 | 7 | import org.junit.Test; 8 | 9 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 10 | 11 | public class InternalStaticITCase { 12 | @Test 13 | public void testDefaultLocale() throws Exception { 14 | Locale def = Locale.getDefault(); 15 | Locale.setDefault(Locale.GERMAN); 16 | assertSame(Locale.GERMAN,Locale.getDefault()); 17 | Reinitializer.markAllClassesForReinit(); 18 | assertSame(def,Locale.getDefault()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/OtherClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | public class OtherClass { 4 | public static int foo = 5; 5 | public int x = 5; 6 | } 7 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/OtherOtherClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | public class OtherOtherClass { 4 | static int foo; 5 | // static OtherClass baz = new OtherClass(); 6 | static int baz() 7 | { 8 | return OtherClass.foo; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/ReflectionITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotEquals; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | import org.junit.Test; 9 | 10 | import edu.columbia.cs.psl.test.vmvm.classes.ClassWithNoInterfaces; 11 | import edu.columbia.cs.psl.test.vmvm.classes.ClassWithOneSField; 12 | import java.edu.columbia.cs.psl.vmvm.runtime.MutableInstance; 13 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 14 | import edu.columbia.cs.psl.vmvm.testsupport.FieldGetter; 15 | 16 | public class ReflectionITCase { 17 | @Test 18 | public void testNumberOfInterfaces() throws Exception { 19 | assertEquals(1, ClassWithOneSField.class.getInterfaces().length); 20 | assertEquals(0, ClassWithNoInterfaces.class.getInterfaces().length); 21 | } 22 | @Test 23 | public void testReinitOnFieldAccess() throws Exception { 24 | Class clz = ClassWithOneSField.class; 25 | Field f = clz.getDeclaredField("foo"); 26 | assertEquals(5, FieldGetter.getFooWithoutInit()); 27 | f.setInt(null, 4); 28 | assertEquals(4, FieldGetter.getFooWithoutInit()); 29 | Reinitializer.markAllClassesForReinit(); 30 | assertEquals(5, f.getInt(null)); 31 | } 32 | 33 | @Test 34 | public void testReinitOnConstructorAccess() throws Exception { 35 | Class clz = ClassWithOneSField.class; 36 | assertEquals(5, FieldGetter.getFooWithoutInit()); 37 | ClassWithOneSField.foo = 2; 38 | Reinitializer.markAllClassesForReinit(); 39 | clz.getConstructor().newInstance(); 40 | assertEquals(5, FieldGetter.getFooWithoutInit()); 41 | 42 | } 43 | 44 | @Test 45 | public void testReinitOnClassLoad() throws Exception { 46 | assertEquals(5, FieldGetter.getFooWithoutInit()); 47 | ClassWithOneSField.foo = 2; 48 | Reinitializer.markAllClassesForReinit(); 49 | Class.forName("edu.columbia.cs.psl.test.vmvm.classes.ClassWithOneSField", true, ReflectionITCase.class.getClassLoader()); 50 | assertEquals(5, FieldGetter.getFooWithoutInit()); 51 | } 52 | 53 | @Test 54 | public void testReinitOnStaticMethod() throws Exception { 55 | Class clz = ClassWithOneSField.class; 56 | assertEquals(5, FieldGetter.getFooWithoutInit()); 57 | ClassWithOneSField.foo = 2; 58 | Reinitializer.markAllClassesForReinit(); 59 | clz.getDeclaredMethod("getFoo").invoke(null); 60 | assertEquals(5, FieldGetter.getFooWithoutInit()); 61 | } 62 | 63 | @Test 64 | public void testCorrectNumberOfFields() throws Exception { 65 | assertEquals(2, ClassWithOneSField.class.getDeclaredFields().length); 66 | for(Field f : ClassWithOneSField.class.getDeclaredFields()) 67 | { 68 | assertNotEquals(f.getType(), MutableInstance.class); 69 | } 70 | } 71 | @Test 72 | public void testCorrectNumberOfMethods() throws Exception { 73 | assertEquals(2, ClassWithOneSField.class.getDeclaredMethods().length); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/ReinitializerITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertSame; 5 | 6 | import org.junit.After; 7 | import org.junit.Test; 8 | 9 | import edu.columbia.cs.psl.test.vmvm.classes.ClassWithOneSField; 10 | import edu.columbia.cs.psl.test.vmvm.classes.IFace; 11 | import edu.columbia.cs.psl.test.vmvm.classes.LaterClass; 12 | import edu.columbia.cs.psl.test.vmvm.classes.SubClassWithAnotherSField; 13 | import edu.columbia.cs.psl.test.vmvm.classes.TryCatchInInitClass; 14 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 15 | import edu.columbia.cs.psl.vmvm.testsupport.FieldGetter; 16 | 17 | public class ReinitializerITCase { 18 | public static int foo = 5; 19 | 20 | @Test 21 | public void testReinitThroughClinit() throws Exception { 22 | ClassWithOneSField.foo = 10; 23 | Reinitializer.markAllClassesForReinit(); 24 | assertEquals(5, LaterClass.bar); 25 | } 26 | 27 | @Test 28 | public void testLongSetter() throws Exception{ 29 | System.out.println(EvilInterface.lon); 30 | } 31 | @Test 32 | public void testReinitDirectIface() throws Exception { 33 | ClassWithOneSField inst = IFace.inst; 34 | Reinitializer.markAllClassesForReinit(); 35 | inst = ClassWithOneSField.inst; 36 | assertSame(IFace.inst, inst); 37 | } 38 | 39 | @Test 40 | public void testTryCatchInClinit() throws Exception { 41 | TryCatchInInitClass c = new TryCatchInInitClass(); 42 | Reinitializer.markAllClassesForReinit(); 43 | c = new TryCatchInInitClass(); 44 | } 45 | 46 | @Test 47 | public void testDirectInit() throws Exception { 48 | ClassWithOneSField f = new ClassWithOneSField(); 49 | assertEquals(5, FieldGetter.getFooWithoutInit()); 50 | ClassWithOneSField.foo = 3; 51 | Reinitializer.markAllClassesForReinit(); 52 | f = new ClassWithOneSField(); 53 | assertEquals(5, FieldGetter.getFooWithoutInit()); 54 | ClassWithOneSField.foo = 3; 55 | Reinitializer.markAllClassesForReinit(); 56 | f = new ClassWithOneSField(4); 57 | assertEquals(5, FieldGetter.getFooWithoutInit()); 58 | } 59 | 60 | @Test 61 | public void testSubClassInit() throws Exception { 62 | SubClassWithAnotherSField f = new SubClassWithAnotherSField(); 63 | assertEquals(5, FieldGetter.getFooWithoutInit()); 64 | assertEquals(4, FieldGetter.getBarWithoutInit()); 65 | SubClassWithAnotherSField.bar = 3; 66 | ClassWithOneSField.foo = 3; 67 | Reinitializer.markAllClassesForReinit(); 68 | f = new SubClassWithAnotherSField(); 69 | assertEquals(4, FieldGetter.getBarWithoutInit()); 70 | assertEquals(5, FieldGetter.getFooWithoutInit()); 71 | ClassWithOneSField.foo = 3; 72 | 73 | Reinitializer.markAllClassesForReinit(); 74 | f = new SubClassWithAnotherSField(5); 75 | assertEquals(5, FieldGetter.getFooWithoutInit()); 76 | } 77 | 78 | @Test 79 | public void testReinitThroughIndirectClassFieldAccess() throws Exception { 80 | SubClassWithAnotherSField f = new SubClassWithAnotherSField(); 81 | assertEquals(5, FieldGetter.getFooWithoutInit()); 82 | assertEquals(4, FieldGetter.getBarWithoutInit()); 83 | SubClassWithAnotherSField.bar = 3; 84 | ClassWithOneSField.foo = 3; 85 | Reinitializer.markAllClassesForReinit(); 86 | assertEquals(5, SubClassWithAnotherSField.foo); 87 | assertEquals(4, FieldGetter.getBarWithoutInit()); 88 | 89 | } 90 | 91 | @Test 92 | public void testReinitThroughIndirectIFaceFieldAccess() throws Exception { 93 | SubClassWithAnotherSField f = new SubClassWithAnotherSField(); 94 | assertEquals(5, FieldGetter.getFooWithoutInit()); 95 | assertEquals(4, FieldGetter.getBarWithoutInit()); 96 | SubClassWithAnotherSField.inst.val = 99; 97 | SubClassWithAnotherSField.bar = 3; 98 | ClassWithOneSField.foo = 3; 99 | Reinitializer.markAllClassesForReinit(); 100 | ClassWithOneSField inst = SubClassWithAnotherSField.inst; 101 | assertEquals(5, inst.val); 102 | assertEquals(5, FieldGetter.getFooWithoutInit()); //ClassWithOneSField should get called via the Iface reinit 103 | assertEquals(4, FieldGetter.getBarWithoutInit()); 104 | 105 | } 106 | 107 | @Test 108 | public void testReinitCalledThroughMethods() throws Exception { 109 | foo = 3; 110 | foo(); 111 | assertEquals(3, foo()); 112 | Reinitializer.markAllClassesForReinit(); 113 | assertEquals(5, foo()); 114 | foo = 4; 115 | assertEquals(4, foo()); 116 | } 117 | 118 | int getOtherClassFoo() { 119 | return OtherClass.foo; 120 | } 121 | 122 | @Test 123 | public void testReinitCalledThroughFields() throws Exception { 124 | OtherClass.foo = 3; 125 | Reinitializer.markAllClassesForReinit(); 126 | assertEquals(5, getOtherClassFoo()); 127 | OtherClass.foo = 4; 128 | assertEquals(4, getOtherClassFoo()); 129 | } 130 | 131 | @After 132 | public void ensureThisClassIsReinited() { 133 | foo(); 134 | } 135 | 136 | @Test 137 | public void testInterface() throws Exception { 138 | System.out.println("Testinterface"); 139 | EvilInterface.baz.put("bar", "baz"); 140 | assertEquals(1, EvilInterface.baz.size()); 141 | Reinitializer.markAllClassesForReinit(); 142 | assertEquals(0, EvilInterface.baz.size()); 143 | } 144 | 145 | static int foo() { 146 | return foo; 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/SystemPropertiesITCase.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm; 2 | 3 | import static org.junit.Assert.assertNull; 4 | 5 | import org.junit.Test; 6 | 7 | import java.edu.columbia.cs.psl.vmvm.runtime.Reinitializer; 8 | 9 | public class SystemPropertiesITCase { 10 | @Test 11 | public void testSystemProps() throws Exception { 12 | System.setProperty("foo", "bar"); 13 | Reinitializer.markAllClassesForReinit(); 14 | assertNull(System.getProperty("foo")); 15 | System.out.println(System.getProperty("foo")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/ClassWithNoInterfaces.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public class ClassWithNoInterfaces { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/ClassWithOneSField.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public class ClassWithOneSField implements IFace { 4 | public static int foo = 5; 5 | public int val = 5; 6 | 7 | static 8 | { 9 | System.out.println("Classwonesf init"); 10 | } 11 | public ClassWithOneSField() 12 | { 13 | 14 | } 15 | public ClassWithOneSField(int baz) 16 | { 17 | 18 | } 19 | static int getFoo() 20 | { 21 | return foo; 22 | } 23 | public static ClassWithOneSField getInst() 24 | { 25 | return inst; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/EEnum.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public enum EEnum { 4 | A("a"), B("b"), C("c"); 5 | private final String name; 6 | EEnum(String name) 7 | { 8 | this.name= name; 9 | } 10 | public String getName() { 11 | return name; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/Foo.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public class Foo { 4 | public static void main(String[] args) { 5 | System.out.println(SubClassWithAnotherSField.foo); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/IFace.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public interface IFace { 4 | public static final ClassWithOneSField inst = new ClassWithOneSField(); 5 | } 6 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/LaterClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public interface LaterClass { 4 | public static final int bar = ClassWithOneSField.foo; 5 | } 6 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/SubClassWithAnotherSField.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public class SubClassWithAnotherSField extends ClassWithOneSField { 4 | static{ 5 | System.out.println("SubClassWithAnotherSField init"); 6 | } 7 | public static int bar = 4; 8 | 9 | public SubClassWithAnotherSField() { 10 | } 11 | 12 | public SubClassWithAnotherSField(int baz) { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/test/vmvm/classes/TryCatchInInitClass.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.test.vmvm.classes; 2 | 3 | public class TryCatchInInitClass { 4 | static Class c; 5 | 6 | static { 7 | try{ 8 | c = Class.forName("foo"); 9 | } 10 | catch(Throwable t) 11 | { 12 | 13 | } 14 | } 15 | static void foo() 16 | { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vmvm/src/test/java/edu/columbia/cs/psl/vmvm/testsupport/FieldGetter.java: -------------------------------------------------------------------------------- 1 | package edu.columbia.cs.psl.vmvm.testsupport; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import edu.columbia.cs.psl.test.vmvm.classes.ClassWithOneSField; 6 | import edu.columbia.cs.psl.test.vmvm.classes.IFace; 7 | import edu.columbia.cs.psl.test.vmvm.classes.SubClassWithAnotherSField; 8 | 9 | public class FieldGetter { 10 | public static int getFooWithoutInit() { 11 | try { 12 | Field f = ClassWithOneSField.class.getDeclaredField("foo"); 13 | return f.getInt(null); 14 | } catch (Throwable t) { 15 | t.printStackTrace(); 16 | } 17 | return -1; 18 | } 19 | 20 | public static int getBarWithoutInit() { 21 | try { 22 | Field f = SubClassWithAnotherSField.class.getDeclaredField("bar"); 23 | return f.getInt(null); 24 | } catch (Throwable t) { 25 | t.printStackTrace(); 26 | } 27 | return -1; 28 | } 29 | 30 | public static ClassWithOneSField getInstWithoutInit() { 31 | try { 32 | Field f = IFace.class.getDeclaredField("inst"); 33 | return (ClassWithOneSField) f.get(null); 34 | } catch (Throwable t) { 35 | t.printStackTrace(); 36 | } 37 | return null; 38 | } 39 | } 40 | --------------------------------------------------------------------------------