單例模式的終結者——setAccessible(true),setaccessibletrue

來源:互聯網
上載者:User

單例模式的終結者——setAccessible(true),setaccessibletrue

先來看下“傳統”的單例模式

package go.derek;public class Singleton{public static int times;private Singleton(){//構造器被調用的時候會列印出次數System.out.println("單例構造器被調用"+(++times)+"兩次");}private final static Singleton instance=new Singleton();public static Singleton getInstance(){return instance;}public void doSomething(){System.out.println("do something");}}
下面是測試類別主函數:
package go.derek;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//通過單例模式獲得單例對象obj1Singleton obj1=Singleton.getInstance();//執行一次doSomething方法obj1.doSomething();//觀察控制台,這次獲得的obj2對象跟obj1是同一個單例,沒有調用構造器Singleton obj2=Singleton.getInstance();obj2.doSomething();//下面厲害的來了,首先拿到萬能的Class對象Class<Singleton> clazz=Singleton.class;//然後拿到構造器,使用這個方法私人的構造器也可以拿到Constructor<Singleton> c=clazz.getDeclaredConstructor();//設定在使用構造器的時候不執行許可權檢查c.setAccessible(true);//由於沒有了許可權檢查,所以在Singleton類外面也可以建立對象了,然後執行方法//觀察控制台,私人構造器又被調用了一次,單例模式被攻陷了,執行方法成功。c.newInstance().doSomething();}}

運行結果如下:

單例構造器被調用1兩次
do something
do something
單例構造器被調用2兩次
do something

試想一下,如果某個惡意用戶端通過上面的方式,就可以為所欲為了,所以為了避免出現這種情況,可以再構造器被第二次調用的時候拋出一個異常

package go.derek;public class Singleton{public static int times;private Singleton() {//構造器被調用的時候會列印出次數System.out.println("單例構造器被調用"+(++times)+"兩次");if(instance!=null){throw new IllegalArgumentException("單例構造器不能重複使用");}}private final static Singleton instance=new Singleton();public static Singleton getInstance(){return instance;}public void doSomething(){System.out.println("do something");}}
運行結果如下:

單例構造器被調用1兩次
do something
do something
單例構造器被調用2兩次
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at go.derek.Test.main(Test.java:24)
Caused by: java.lang.IllegalArgumentException: 單例構造器不能重複使用
at go.derek.Singleton.<init>(Singleton.java:10)
... 5 more

目的達到了~


私人的靜態方法setAccessible中的解釋

這個主要是利用反射機制調整目標對象的存取權限的時候用到。
這個方法裡就是利用AccessController類,以特權方式去執行AccessibleObject裡面一層的setAccessible函數。因為這一層函數內會利用checkPermission最終到BasicPermission去檢查許可權。
 
百度手機開發提供的例子BMapApiDemo怎一運行就出錯

android使用自訂UncaughtExceptionHandler 處理常式崩潰
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Properties;
import java.util.TreeSet;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

/**
* UncaughtException處理類,當程式發生Uncaught異常的時候,有該類 來接管程式,並記錄 發送錯誤報表.. 註冊方式
* CrashHandler crashHandler = CrashHandler.getInstance(); //註冊crashHandler
* crashHandler.init(getApplicationContext()); //發送以前沒發送的報告(可選)
* crashHandler.sendPreviousReportsToServer();
*
*/
public class CrashHandler implements UncaughtExceptionHandler {
/** Debug Log tag */
public static final String TAG = "CrashHandler";
/**
* 是否開啟日誌輸出,在Debug狀態下開啟, 在Release狀態下關閉以提示程式效能
* */
public static final boolean DEBUG = true;
/** 系統預設的UncaughtException處理類 */
private Thread.UncaughtExceptionHandler mDefaultHandler;
/** CrashHandler執行個體 */
private static CrashHandler INSTANCE;
/** 程式的Context對象 */
private Context mContext;

/** 使用Properties......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.