[Java] Error 혹은 Debug시 등장하는 method인 access$000

프로그래밍 팁 2015. 8. 20. 23:57

 안드로이드 프레임워크를 공부하면서 종종 신기한 경우들을 마주치곤 합니다. 그 중 하나가 바로 실제 코드상에는 존재하지 않던 method가 디버깅을 할 때 예상치 못하게 등장하기 때문입니다.




 분명 소스코드 상에서는 존재 자체가 없었던 method인 'access$000'가 이렇게 디버깅을 하던 도중 발견되는 경우가 종종 있습니다. 과연 이것의 정체는 무엇일까요?


 이 문제의 원인은 바로 Java 언어의 특징 중 하나인 Inner class에서 원인을 찾을 수 있습니다.


 Java를 공부하신 분들이라면 누구나 아시는 듯이 Inner class는 말 그대로 Class 안에 내포된 Class를 의미합니다. C언어에서 마치 Struct 구조체 안에 또다른 Struct를 품은 듯한 형태를 띄고 있는 구조라고 이해하시면 되겠습니다.


아래는 Inner class가 구현되어 있는 예제입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Test {
 
  public void func() {
    System.out.println(new Inner().a);
    System.out.println(new Inner().getInt());
    System.out.println(new Inner2().b);
    System.out.println(new Inner2().getInt());
  }
 
  class Inner {
    private int a;
 
    public int getInt() {
      return a;
    }
  }
 
  class Inner2 {
    int b;
 
    public int getInt() {
      return b;
    }
  }
}
cs


 위의 예제는 Test 클래스 안에 두 개의 Inner class로 구성되어 있는 소스코드입니다. Test 클래스의 입장에서 Inner class는 private 인 경우에도 접근이 가능하여 위의 func() method에서 실행되는 모든 함수들이 제 기능을 하는 것을 확인하실 수 있습니다.


 그런데 여기서 문제가 발생하게 됩니다. Java의 소스코드를 컴파일한 결과물인 bytecode는 Inner class를 고려하지 않는다는 점입니다. 이로 인해 bytecode 상에서 func() method는 접근할수 없는 field 값은 Inner 클래스의 a의 값에 접근할 수 없게 됩니다.

 그렇기 때문에 실제 bytecode 상에서는 private로 설정된 내부클래스에 접근할 수 있도록 하기 위해 소스코드를 살짝 바꾸어서 기능을 똑같이 구현되게 하는데 실제 위의 설계된 소스코드를 디컴파일하게 되면 위에서 보았던 메소드인  access$000이 등장하는 것을 알 수 있습니다.


 아래의 예제는 Inner class가 적용되었을 경우를 가장한 예제입니다. 위의 소스코드와 비교하시면 자신이 설계한 소스코드에서 등장하는  access$000이 어느 시점에서 등장하게 되는지 어느 정도 감이 오실 것이라 생각됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Test {
  public void func() {
    System.out.println(Test$Inner.access$000(new Test$Inner(this)));
    System.out.println(new Test$Inner(this).getInt());
    System.out.println(new Test$Inner2(this).b);
    System.out.println(new Test$Inner2(this).getInt());
  }
}
 
class Test$Inner {
  final Test this$0;
 
  private int a;
 
  Test$Inner(Test test) {
    this$0 = test;
  }
 
  public int getInt() {
    return a;
  }
 
  static int access$000(Test$Inner inner) {
    return inner.a;
  }
 
}
 
class Test$Inner2 {
  final Test this$0;
 
  int b;
 
  Test$Inner2(Test test) {
    this$0 = test;
  }
 
  public int getInt() {
    return b;
  }
}
cs


 아래는 제가 안드로이드 프레임워크를 분석하던 도중  access$000가 뜨던 부분입니다. 보시는 대로 new Handler() 방식으로 내부클래스를 구성하고 있으며 이를  access$000 함수명을 통하여 updateWindow() 함수에 접근하고 있는 것을 확인할 수 있습니다.


/frameworks/base/core/java/android/view/SurfaceView.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SurfaceView extends View {
 
....
 
    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case KEEP_SCREEN_ON_MSG: {
                    setKeepScreenOn(msg.arg1 != 0);
                } break;
                case GET_NEW_SURFACE_MSG: {
                    handleGetNewSurface();
                } break;
                case UPDATE_WINDOW_MSG: {
                    updateWindow(falsefalse);
                } break;
            }
        }
    };
 
....
 
}
cs



출저 : http://www.javacodegeeks.com/2012/05/java-pitfalls-field-access-in-inner.html

300x250

Intel Management Engine BIOS Extention 설정시 암호 변경이 안될 때 해결방법

공대생의 팁 2015. 8. 19. 21:12

 Intel 사의 bios를 설정할 때에 사용되는Intel Management Engine BIOS Extention을 처음 사용할 때에 default 암호를 알 수가 없어 이를 어떻게 해야 헤결될 수 있는지 방법을 한참 찾다 설정 방법을 알게 되어 이렇게 포스팅을 하게 되었습니다. 혹시 Intel Management Engine BIOS Extention을 설정하시다가 저와 같이 암호 설정 때문에 애를 먹는 분이라면 본 포스팅이 도움이 되었으면 합니다.


 먼저, Intel Management Engine BIOS Extention에 진입하는 방법부터 알아보도록 하겠습니다. 아래 화면은 Dell사의 컴퓨터를 기준으로 F12 버튼을 누른 후 Boot Device Menu로 진입한 화면입니다.



 이렇게 Boot Device Menu에 진입하게 되면 위와 같은 메뉴들을 확인하실 수 있습니다. 이 중 Intel Management Engine BIOS Extention을 선택하여 진입하도록 합니다.



 그렇게 해서 진입을 하면 아래에서 보는 바와 같이 처음부터 암호를 입력하라는 뜬금없는 화면이 뜨게 됩니다. 우리는 이 암호를 설정한 적도 없음에도 이렇게 버젓이 뜨니 당혹스러울 수 밖에 없는 상황이지요...

 실은 해당 암호는 처음에는 Defalt로 기본 암호가 설정되어 있습니다. 해당 Default 암호는 다음과 같습니다.


admin


 위의 디폴트 암호를 입력하시면 아래와 같이 암호를 새로 설정하라는 안내가 나옵니다.



 그런데 이상하게도 암호를 설정하려 할 때마다 위와 같은 경고문이 뜨면서 변경된 암호를 받아들이지 않는 당혹스러운 상황이 벌어집니다.


Error - Intel(R) ME password change rejected


 위와 같은 일이 발생하는 이유는 자신이 설정한 암호가 해당 프로그램이 요구하는 암호의 기준에 맞지 않아 보안에 약한 암호이기 때문에 위와 같이 자신이 설정한 암호가 거절당하는 상황이 발생하게 됩니다.

 위와 같은 상황이 생기시는 분들이 계신다면 아래의 규칙대로 자신의 암호를 다시 설정하시면 암호를 설정하실 수 있을 것입니다.


 1. 8자 이상의 암호로 구성되어야 합니다.

 2. 1개 이상의 숫자가 암호에 포함되어야 합니다.(1,2,...,0)

 3. 1개 이상의 기호(!,@,#,$,...)가 포함되어야 합니다. 단, '_'는 암호로 설정할 수 있으나 기호로는 예외입니다.

 4. 알파벳 설정시 대문자와 소문자를 섞어서 사용해야 합니다.



 예를 들어 다음과 같이 암호를 설정하시면 확실하게 적용되는 것을 확인하실 수 있습니다.


eLecs20!5



300x250

SurfaceView가 다른 View 클래스와의 차이(updateWindow() method in SurfaceView class)

안드로이드/프레임워크 2015. 8. 17. 20:13

 안드로이드 UI를 설계할 때 주로 사용되는 View의 경우 화면에 한 번 표출되면 특별한 이펙트를 적용하지 않는 한 Activity에서 생성된 모습 그대로의 모습을 유지하는 경우가 대부분입니다.

 반면 SurfaceView의 경우 화면의 변화가 다른 View들에 비해 거의 실시간으로 화면에 변화를 주어야 하는 특성을 가지고 있기 때문에 이를 실시간으로 적용시킬 수 있는 기능이 필요로 하는데 그 중 하나가 updateWindow() 함수입니다.


 아래 간단한 예제를 통해 알아보도록 하겠습니다.


1
surfaceView.setVisibility(View.VISIBLE);
cs


 Application 단계에서 SurfaceView를 화면상에서 보이도록 설정하게 되는 순간 SurfaceView는 화면에 비추어지기 시작합니다.


/frameworks/base/core/java/android/view/SurfaceView.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        mViewVisibility = visibility == VISIBLE;
        boolean newRequestedVisible = mWindowVisibility && mViewVisibility;
        if (newRequestedVisible != mRequestedVisible) {
            // our base class (View) invalidates the layout only when
            // we go from/to the GONE state. However, SurfaceView needs
            // to request a re-layout when the visibility changes at all.
            // This is needed because the transparent region is computed
            // as part of the layout phase, and it changes (obviously) when
            // the visibility changes.
            requestLayout();
        }
        mRequestedVisible = newRequestedVisible;
        updateWindow(falsefalse);
    }
cs


 보시는 바와 같이 SurfaceView를 화면에 비추도록 설정하였을 때 함수 내에 updateWindow() 함수가 호출되고 있는 것을 보실 수 있습니다. 해당 함수는 SurfaceHolder에서 설정한 기능들을 수행하는 데에 사용되며 SurfaceHolder에 대한 자세한 사항은 아래 포스팅을 참조해 주시길 바랍니다.


http://elecs.tistory.com/78


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    private void updateWindow(boolean force, boolean redrawNeeded) {
 
        if (!mHaveFrame) {
            return;
        }
        ViewRootImpl viewRoot = getViewRootImpl();
        if (viewRoot != null) {
            mTranslator = viewRoot.mTranslator;
        }
 
        if (mTranslator != null) {
            mSurface.setCompatibilityTranslator(mTranslator);
        }
 
        int myWidth = mRequestedWidth;
        if (myWidth <= 0) myWidth = getWidth();
        int myHeight = mRequestedHeight;
        if (myHeight <= 0) myHeight = getHeight();
 
        getLocationInWindow(mLocation);
        final boolean creating = mWindow == null;
        final boolean formatChanged = mFormat != mRequestedFormat;
        final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
        final boolean visibleChanged = mVisible != mRequestedVisible;
 
        if (force || creating || formatChanged || sizeChanged || visibleChanged
            || mLeft != mLocation[0|| mTop != mLocation[1]
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
 
            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged
                    + " left=" + (mLeft != mLocation[0])
                    + " top=" + (mTop != mLocation[1]));
 
            try {
                final boolean visible = mVisible = mRequestedVisible;
                mLeft = mLocation[0];
                mTop = mLocation[1];
                mWidth = myWidth;
                mHeight = myHeight;
                mFormat = mRequestedFormat;
 
                // Scaling/Translate window's layout here because mLayout is not used elsewhere.
 
                // Places the window relative
                mLayout.x = mLeft;
                mLayout.y = mTop;
                mLayout.width = getWidth();
                mLayout.height = getHeight();
                if (mTranslator != null) {
                    mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
                }
 
                mLayout.format = mRequestedFormat;
                mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                              | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                              | WindowManager.LayoutParams.FLAG_SCALED
                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                              | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                              ;
                if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
                    mLayout.privateFlags |=
                            WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                }
                mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 
                if (mWindow == null) {
                    Display display = getDisplay();
                    mWindow = new MyWindow(this);
                    mLayout.type = mWindowType;
                    mLayout.gravity = Gravity.START|Gravity.TOP;
                    mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
                            mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
                }
 
                boolean realSizeChanged;
                boolean reportDrawNeeded;
 
                int relayoutResult;
 
                mSurfaceLock.lock();
                try {
                    mUpdateWindowNeeded = false;
                    reportDrawNeeded = mReportDrawNeeded;
                    mReportDrawNeeded = false;
                    mDrawingStopped = !visible;
 
                    if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
 
                    relayoutResult = mSession.relayout(
                        mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                            visible ? VISIBLE : GONE,
                            WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
                            mWinFrame, mOverscanInsets, mContentInsets,
                            mVisibleInsets, mConfiguration, mNewSurface);
                    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                        mReportDrawNeeded = true;
                    }
 
                    if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
                            + ", vis=" + visible + ", frame=" + mWinFrame);
 
                    mSurfaceFrame.left = 0;
                    mSurfaceFrame.top = 0;
                    if (mTranslator == null) {
                        mSurfaceFrame.right = mWinFrame.width();
                        mSurfaceFrame.bottom = mWinFrame.height();
                    } else {
                        float appInvertedScale = mTranslator.applicationInvertedScale;
                        mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
                        mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
                    }
 
                    final int surfaceWidth = mSurfaceFrame.right;
                    final int surfaceHeight = mSurfaceFrame.bottom;
                    realSizeChanged = mLastSurfaceWidth != surfaceWidth
                            || mLastSurfaceHeight != surfaceHeight;
                    mLastSurfaceWidth = surfaceWidth;
                    mLastSurfaceHeight = surfaceHeight;
                } finally {
                    mSurfaceLock.unlock();
                }
 
                try {
                    redrawNeeded |= creating | reportDrawNeeded;
 
                    SurfaceHolder.Callback callbacks[] = null;
 
                    final boolean surfaceChanged = (relayoutResult
                            & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
                    if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                        mSurfaceCreated = false;
                        if (mSurface.isValid()) {
                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
                            callbacks = getSurfaceCallbacks();
                            for (SurfaceHolder.Callback c : callbacks) {
                                c.surfaceDestroyed(mSurfaceHolder);
                            }
                        }
                    }
 
                    mSurface.transferFrom(mNewSurface);
 
                    if (visible && mSurface.isValid()) {
                        if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
                            mSurfaceCreated = true;
                            mIsCreating = true;
                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
                            }
                            for (SurfaceHolder.Callback c : callbacks) {
                                c.surfaceCreated(mSurfaceHolder);
                            }
                        }
                        if (creating || formatChanged || sizeChanged
                                || visibleChanged || realSizeChanged) {
                            if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
                                    + " w=" + myWidth + " h=" + myHeight);
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
                            }
                            for (SurfaceHolder.Callback c : callbacks) {
                                c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
                            }
                        }
                        if (redrawNeeded) {
                            if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
                            if (callbacks == null) {
                                callbacks = getSurfaceCallbacks();
                            }
                            for (SurfaceHolder.Callback c : callbacks) {
                                if (c instanceof SurfaceHolder.Callback2) {
                                    ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
                                            mSurfaceHolder);
                                }
                            }
                        }
                    }
                } finally {
                    mIsCreating = false;
                    if (redrawNeeded) {
                        if (DEBUG) Log.i(TAG, "finishedDrawing");
                        mSession.finishDrawing(mWindow);
                    }
                    mSession.performDeferredDestroy(mWindow);
                }
            } catch (RemoteException ex) {
            }
            if (DEBUG) Log.v(
                TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                " w=" + mLayout.width + " h=" + mLayout.height +
                ", frame=" + mSurfaceFrame);
        }
    }
cs


300x250